/*---------- 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 ----------*/
/*---------- resolver management ----------*/
-IdDataTable adnstcl_resolvers= { "adns-res" };
-
struct Resolver {
int ix; /* first! */
Tcl_Interp *interp;
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;
}
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 }
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;
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;
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");
}
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;
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,
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;
/*---------- 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;
}
}
-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;
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
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);
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;
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;
}
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
+};