X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=adns%2Fadns.c;h=1ecb6729c19b635e343554beec29ee1211fc1c86;hb=9b2c18cc9d122b45f9e737864921d32baa599f0c;hp=34ca06ce1e72055693299202c22603a5a9643104;hpb=cc93324adf9022c227322bc691103b56c2a70b68;p=chiark-tcl.git diff --git a/adns/adns.c b/adns/adns.c index 34ca06c..1ecb672 100644 --- a/adns/adns.c +++ b/adns/adns.c @@ -58,10 +58,12 @@ /*---------- important types and forward declarations ----------*/ +typedef struct Query Query; typedef struct Resolver Resolver; typedef struct OptionInfo OptionInfo; static void asynch_check(Resolver *res); static void asynch_sethandlers(Resolver *res, int shutdown); +static void asynch_query_dispose(Tcl_Interp *interp, Query *query); /*---------- common resolver/query option processing ----------*/ @@ -144,8 +146,6 @@ static int parse_options(Tcl_Interp *ip, int objc, Tcl_Obj *const *objv, /*---------- resolver management ----------*/ -IdDataTable adnstcl_resolvers= { "adns-res" }; - struct Resolver { int ix; /* first! */ Tcl_Interp *interp; @@ -202,15 +202,33 @@ static void adnslogfn_callback(adns_state ads, void *logfndata, abort(); /* fixme implement adns_logcallbackfn */ } -int do_adns_destroy_resolver(ClientData cd, Tcl_Interp *ip, void *res_v) { - Resolver *res= res_v; - tabledataid_disposing(res,&adnstcl_resolvers); - if (res->ads) adns_finish(res->ads); +static void destroy_resolver(Tcl_Interp *ip, Resolver *res) { + void *query_v; + adns_query aqu; + + if (res->ads) { + /* although adns would throw these away for us, we need to + * destroy our own data too and only adns has a list of them */ + for (;;) { + adns_forallqueries_begin(res->ads); + aqu= adns_forallqueries_next(res->ads, &query_v); + if (!aqu) break; + asynch_query_dispose(ip, query_v); + } + adns_finish(res->ads); + } asynch_sethandlers(res,1); TFREE(res); - /* fixme what about outstanding queries */ /* fixme what about the default resolver */ - /* fixme what if the tcl interpreter gets deleted */ +} + +static void destroy_resolver_idtabcb(Tcl_Interp *ip, void *resolver_v) { + destroy_resolver(ip,resolver_v); +} + +int do_adns_destroy_resolver(ClientData cd, Tcl_Interp *ip, void *res_v) { + destroy_resolver(ip,res_v); + tabledataid_disposing(ip,res_v,&adnstcl_resolvers); return TCL_OK; } @@ -262,6 +280,10 @@ int do_adns_new_resolver(ClientData cd, Tcl_Interp *ip, return rc; } +const IdDataSpec adnstcl_resolvers= { + "adns-res", "adns-resolvers-table", destroy_resolver_idtabcb +}; + /*---------- query, query option and answers - common stuff ----------*/ #define RRTYPE_EXACTLY(t) { #t, adns_r_##t } @@ -316,7 +338,7 @@ static const OptionInfo query_optioninfos[]= { static int query_submit(Tcl_Interp *ip, const AdnsTclRRTypeInfo *type, const char *domain, int queryopts_objc, Tcl_Obj *const *queryopts_objv, - adns_query *aqu_r, OptionParse *op) { + adns_query *aqu_r, void *context, OptionParse *op) { struct sockaddr sa; static const int aftry[]= { AF_INET, AF_INET6 }; int rc, r, ec; @@ -324,7 +346,8 @@ static int query_submit(Tcl_Interp *ip, op->aflags= adns_qf_owner; op->sflags= 0; - op->resolver= 0; + op->resolver= 0; /* fixme default */ + op->reverseany= 0; rc= parse_options(ip, queryopts_objc,queryopts_objv, query_optioninfos,op); if (rc) return rc; @@ -344,13 +367,13 @@ static int query_submit(Tcl_Interp *ip, if (op->reverseany) { ec= adns_submit_reverse_any(ads, &sa, op->reverseany, - type->number, op->aflags, 0, aqu_r); + type->number, op->aflags, context, aqu_r); } else if (op->sflags & oisf_reverse) { ec= adns_submit_reverse(ads, &sa, - type->number, op->aflags, 0, aqu_r); + type->number, op->aflags, context, aqu_r); } else { ec= adns_submit(ads, domain, - type->number, op->aflags, 0, aqu_r); + type->number, op->aflags, context, aqu_r); } if (ec) return posixerr(ip,ec,"submit adns query"); @@ -370,7 +393,7 @@ static void make_resultstatus(Tcl_Interp *ip, adns_status status, } static Tcl_Obj *make_resultrdata(Tcl_Interp *ip, adns_answer *answer) { - Tcl_Obj **rdata; + Tcl_Obj **rdata, *rl; int i, rrsz; adns_status st; char *datap, *rdatastring; @@ -384,8 +407,9 @@ static Tcl_Obj *make_resultrdata(Tcl_Interp *ip, adns_answer *answer) { rdata[i]= ret_string(ip, rdatastring); free(rdatastring); } + rl= Tcl_NewListObj(answer->nrrs, rdata); TFREE(rdata); - return Tcl_NewListObj(answer->nrrs, rdata); + return rl; } static void make_resultlist(Tcl_Interp *ip, adns_answer *answer, @@ -408,7 +432,7 @@ static int synch(Tcl_Interp *ip, const AdnsTclRRTypeInfo *rrtype, Resolver *res; int rc, ec; - rc= query_submit(ip,rrtype,domain,objc,objv,&aqu,&op); + rc= query_submit(ip,rrtype,domain,objc,objv,&aqu,0,&op); if (rc) return rc; res= op.resolver; @@ -458,15 +482,13 @@ int do_adns_synch(ClientData cd, Tcl_Interp *ip, /*---------- asynchronous query handling ----------*/ -typedef struct { +struct Query { int ix; /* first! */ Resolver *res; adns_query aqu; ScriptToInvoke on_yes, on_no, on_fail; Tcl_Obj *xargs; -} Query; - -IdDataTable adnstcl_queries= { "adns" }; +}; static void asynch_timerhandler(void *res_v) { Resolver *res= res_v; @@ -526,16 +548,6 @@ static void asynch_sethandlers(Resolver *res, int shutdown) { } } -static void asynch_query_dispose(Query *query) { - tabledataid_disposing(query, &adnstcl_queries); - scriptinv_cancel(&query->on_yes); - scriptinv_cancel(&query->on_no); - scriptinv_cancel(&query->on_fail); - if (query->xargs) Tcl_DecrRefCount(query->xargs); - if (query->aqu) adns_cancel(query->aqu); - TFREE(query); -} - static void asynch_check(Resolver *res) { Tcl_Interp *interp= res->interp; adns_query aqu; @@ -553,7 +565,7 @@ static void asynch_check(Resolver *res) { query= query_v; query->aqu= 0; - tabledataid_disposing(query, &adnstcl_queries); + tabledataid_disposing(interp, query, &adnstcl_queries); si= (!answer->status ? si= &query->on_yes : answer->status > adns_s_max_tempfail ? &query->on_no @@ -562,7 +574,7 @@ static void asynch_check(Resolver *res) { make_resultlist(interp, answer, results); free(answer); scriptinv_invoke(si, RESULTLIST_LLEN, results); - asynch_query_dispose(query); + asynch_query_dispose(interp, query); } asynch_sethandlers(res,0); @@ -586,7 +598,7 @@ int do_adns_asynch(ClientData cd, Tcl_Interp *ip, scriptinv_init(&query->on_fail); query->xargs= 0; - rc= query_submit(ip,rrtype,domain,objc,objv,&query->aqu,&op); + rc= query_submit(ip,rrtype,domain,objc,objv,&query->aqu,query,&op); if (rc) goto x_rc; res= op.resolver; @@ -601,7 +613,7 @@ int do_adns_asynch(ClientData cd, Tcl_Interp *ip, return TCL_OK; x_rc: - if (query) asynch_query_dispose(query); + if (query) asynch_query_dispose(ip, query); if (res) asynch_sethandlers(res,0); return rc; } @@ -609,8 +621,25 @@ int do_adns_asynch(ClientData cd, Tcl_Interp *ip, int do_adns_asynch_cancel(ClientData cd, Tcl_Interp *ip, void *query_v) { Query *query= query_v; Resolver *res= query->res; - - asynch_query_dispose(query); + asynch_query_dispose(ip, query); asynch_sethandlers(res,0); return TCL_OK; } + +static void asynch_query_dispose(Tcl_Interp *interp, Query *query) { + tabledataid_disposing(interp, query, &adnstcl_queries); + scriptinv_cancel(&query->on_yes); + scriptinv_cancel(&query->on_no); + scriptinv_cancel(&query->on_fail); + if (query->xargs) Tcl_DecrRefCount(query->xargs); + if (query->aqu) adns_cancel(query->aqu); + TFREE(query); +} + +static void destroy_query_idtabcb(Tcl_Interp *interp, void *query_v) { + asynch_query_dispose(interp, query_v); +} + +const IdDataSpec adnstcl_queries= { + "adns", "adns-query-table", destroy_query_idtabcb +};