chiark / gitweb /
many improvements: use Get/SetAssocData for idtables to avoid globals, and adns bindi...
authorian <ian>
Wed, 15 Dec 2004 23:39:47 +0000 (23:39 +0000)
committerian <ian>
Wed, 15 Dec 2004 23:39:47 +0000 (23:39 +0000)
adns/adns.c
base/chiark-tcl.h
base/idtable.c
base/tables-examples.tct
dgram/dgram.c
hbytes/hbytes.h
tuntap/tuntap.c

index 34ca06c..1ecb672 100644 (file)
 
 /*---------- 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
+};
index 2b03287..b49301f 100644 (file)
@@ -215,10 +215,9 @@ void scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj **argv);
 /* from idtable.c */
 
 typedef struct {
-  const char *const prefix;
-  int n;
-  void **a;
-} IdDataTable;
+  const char *valprefix, *assockey;
+  void (*destroyitem)(Tcl_Interp *ip, void *val);
+} IdDataSpec;
 
 /* The stored struct must start with a single int, conventionally
  * named `ix'.  When the struct is returned for the first time ix must
@@ -226,10 +225,10 @@ typedef struct {
  * the struct is registered by the iddatatable machinery. */
 
 extern Tcl_ObjType tabledataid_nearlytype;
-int tabledataid_parse(Tcl_Interp *ip, Tcl_Obj *o, IdDataTable *tab);
-void tabledataid_disposing(void *val, IdDataTable *tab);
+int tabledataid_parse(Tcl_Interp *ip, Tcl_Obj *o, const IdDataSpec *idds);
+void tabledataid_disposing(Tcl_Interp *ip, void *val, const IdDataSpec *idds);
   /* call this when you destroy the struct, to remove its name;
-   * _disposing is idempotent*/
+   * _disposing is idempotent */
 
 /* from adns.c */
 
@@ -238,16 +237,16 @@ typedef struct {
   adns_rrtype number;
 } AdnsTclRRTypeInfo;
 
-extern IdDataTable adnstcl_queries, adnstcl_resolvers;
+extern const IdDataSpec adnstcl_queries, adnstcl_resolvers;
 
 /* from dgram.c */
 
-extern IdDataTable dgram_socks;
+extern const IdDataSpec dgram_socks;
 int newfdposixerr(Tcl_Interp *ip, int fd, const char *m);
 
 /* from tuntap.c */
 
-extern IdDataTable tuntap_socks;
+extern const IdDataSpec tuntap_socks;
 
 /* from hook.c */
 
index f64a101..b23a97c 100644 (file)
 
 /* Arg parsing */
 
-static void setobjdataid(Tcl_Obj *o, int ix, IdDataTable *tab) {
-  unsigned long *ulp;
+typedef struct {
+  const IdDataSpec *idds;
+  int n;
+  void **a;
+} IdDataAssocData;
+
+typedef struct {
+  Tcl_Interp *interp;
+  IdDataAssocData *assoc;
+  int ix;
+} IdDataValue;
+
+static void assoc_del(ClientData assoc_cd, Tcl_Interp *ip) {
+  IdDataAssocData *assoc;
+  int ix;
+  void **p, *v;
+
+  assoc= assoc_cd;
+  for (ix=0, p=assoc->a; ix<assoc->n; ix++, p++) {
+    v= *p;
+    if (!v) continue;
+    assert(*(int*)v == ix);
+    *(int*)v= -1;
+    assoc->idds->destroyitem(ip,v);
+    *p= 0;
+  }
+  TFREE(assoc->a);
+  TFREE(assoc);
+}
+
+static void setobjdataid(Tcl_Interp *interp, Tcl_Obj *o,
+                        int ix, const IdDataSpec *idds) {
+  IdDataValue *dv;
+  IdDataAssocData *assoc;
+
+  assoc= Tcl_GetAssocData(interp, (char*)idds->assockey, 0);
+  if (!assoc) {
+    assoc= TALLOC(sizeof(*assoc));
+    assoc->idds= idds;
+    assoc->n= 0;
+    assoc->a= 0;
+    Tcl_SetAssocData(interp, (char*)idds->assockey, assoc_del, assoc);
+  }
+  
+  dv= TALLOC(sizeof(*dv));
+  dv->interp= interp;
+  dv->assoc= assoc;
+  dv->ix= ix;
   
-  ulp= TALLOC(sizeof(unsigned long));
-  *ulp= ix;
-  o->internalRep.twoPtrValue.ptr1= tab;
-  o->internalRep.twoPtrValue.ptr2= ulp;
   o->typePtr= &tabledataid_nearlytype;
+  o->internalRep.otherValuePtr= dv;
 }
 
-int tabledataid_parse(Tcl_Interp *ip, Tcl_Obj *o, IdDataTable *tab) {
+int tabledataid_parse(Tcl_Interp *ip, Tcl_Obj *o, const IdDataSpec *idds) {
   int l;
   unsigned long ul;
+  IdDataValue *dv;
+  IdDataAssocData *assoc;
   char *ep, *str;
 
-  if (o->typePtr == &tabledataid_nearlytype &&
-      o->internalRep.twoPtrValue.ptr1 == tab) return TCL_OK;
+  if (o->typePtr != &tabledataid_nearlytype) goto convert;
+
+  dv= o->internalRep.otherValuePtr;
+  if (dv->interp != ip) goto convert;
+  assoc= dv->assoc;
+  if (dv->assoc->idds != idds) goto convert;
 
-  l= strlen(tab->prefix);
+  return TCL_OK;
+
+convert:
+  l= strlen(idds->valprefix);
   str= Tcl_GetStringFromObj(o,0);
-  if (memcmp(str,tab->prefix,l))
+  if (memcmp(str,idds->valprefix,l))
     return staticerr(ip,"bad id (wrong prefix)",0);
+
   errno=0; ul=strtoul(str+l,&ep,10);
   if (errno || *ep) return staticerr(ip,"bad id number",0);
   if (ul > INT_MAX) return staticerr(ip,"out of range id number",0);
 
   objfreeir(o);
-  setobjdataid(o,ul,tab);
+  setobjdataid(ip,o,ul,idds);
   return TCL_OK;
 }
 
-void tabledataid_disposing(void *val, IdDataTable *tab) {
-  int ix;
-
-  ix= *(int*)val;
-  if (ix==-1) return;
-  assert(tab->a[ix] == val);
-  tab->a[ix]= 0;
-  *(int*)val= -1;
-}
-
-int pat_iddata(Tcl_Interp *ip, Tcl_Obj *o, void **rv, IdDataTable *tab) {
+int pat_iddata(Tcl_Interp *ip, Tcl_Obj *o, void **rv, const IdDataSpec *idds) {
   int rc, ix;
+  IdDataValue *dv;
+  IdDataAssocData *assoc;
   void *r;
   
-  rc= tabledataid_parse(ip,o,tab);
+  rc= tabledataid_parse(ip,o,idds);
   if (rc) return rc;
 
-  ix= *(unsigned long*)o->internalRep.twoPtrValue.ptr2;
-  if (ix >= tab->n || !(r= tab->a[ix]))
+  dv= o->internalRep.otherValuePtr;
+  ix= dv->ix;
+  assoc= dv->assoc;
+
+  if (ix >= assoc->n || !(r= assoc->a[ix]))
     return staticerr(ip,"id not in use",0);
 
   assert(*(int*)r == ix);
@@ -64,59 +112,86 @@ int pat_iddata(Tcl_Interp *ip, Tcl_Obj *o, void **rv, IdDataTable *tab) {
   return TCL_OK;
 }
 
-Tcl_Obj *ret_iddata(Tcl_Interp *ip, void *val, IdDataTable *tab) {
+Tcl_Obj *ret_iddata(Tcl_Interp *ip, void *val, const IdDataSpec *idds) {
   /* Command procedure implementation may set val->ix,
    * ie *(int*)val, to -1, to mean it's a new struct.  Otherwise
    * it had better be an old one !
    */
   Tcl_Obj *o;
+  IdDataValue *dv;
+  IdDataAssocData *assoc;
   int ix;
 
+  o= Tcl_NewObj();
+  setobjdataid(ip,o,0,idds);
+  dv= o->internalRep.otherValuePtr;
+  assoc= dv->assoc;
+
   ix= *(int*)val;
   if (ix==-1) {
-    for (ix=0; ix<tab->n && tab->a[ix]; ix++);
-    if (ix>=tab->n) {
-      tab->n += 2;
-      tab->n *= 2;
-      tab->a= (void*)Tcl_Realloc((void*)tab->a, tab->n*sizeof(*tab->a));
-      while (ix<tab->n) tab->a[ix++]=0;
+    for (ix=0; ix<assoc->n && assoc->a[ix]; ix++);
+    if (ix>=assoc->n) {
+      assoc->n += 2;
+      assoc->n *= 2;
+      assoc->a= TREALLOC(assoc->a, assoc->n*sizeof(*assoc->a));
+      while (ix<assoc->n) assoc->a[ix++]=0;
       ix--;
     }
-    tab->a[ix]= val;
+    assoc->a[ix]= val;
     *(int*)val= ix;
   } else {
-    assert(val == tab->a[ix]);
+    assert(val == assoc->a[ix]);
   }
-
-  o= Tcl_NewObj();
-  setobjdataid(o,ix,tab);
+  dv->ix= ix;
   Tcl_InvalidateStringRep(o);
   return o;
 }
 
+void tabledataid_disposing(Tcl_Interp *ip, void *val, const IdDataSpec *idds) {
+  IdDataAssocData *assoc;
+  int ix;
+
+  ix= *(int*)val;
+  if (ix==-1) return;
+
+  assoc= Tcl_GetAssocData(ip, (char*)idds->assockey, 0);
+  assert(assoc->a[ix] == val);
+  assoc->a[ix]= 0;
+  *(int*)val= -1;
+}
+
 static int tabledataid_nt_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
   abort();
 }
 
 static void tabledataid_nt_free(Tcl_Obj *o) {
-  TFREE(o->internalRep.twoPtrValue.ptr2);
-  o->internalRep.twoPtrValue.ptr2= 0;
+  TFREE(o->internalRep.otherValuePtr);
+  o->internalRep.otherValuePtr= 0;
 }
 
 static void tabledataid_nt_dup(Tcl_Obj *src, Tcl_Obj *dup) {
-  setobjdataid(dup,*(unsigned long*)src->internalRep.twoPtrValue.ptr2,
-              src->internalRep.twoPtrValue.ptr1);
+  IdDataValue *sv, *dv;
+
+  sv= src->internalRep.otherValuePtr;
+  dv= TALLOC(sizeof(*dv));
+  *dv= *sv;
+  dup->typePtr= &tabledataid_nearlytype;
+  dup->internalRep.otherValuePtr= dv;
 }
 
 static void tabledataid_nt_ustr(Tcl_Obj *o) {
+  const IdDataValue *dv;
+  const IdDataAssocData *assoc;
+  const IdDataSpec *idds;
   char buf[75];
-  const char *prefix;
 
-  prefix= ((IdDataTable*)o->internalRep.twoPtrValue.ptr1)->prefix;
-  snprintf(buf,sizeof(buf), "%lu",
-          *(unsigned long*)o->internalRep.twoPtrValue.ptr2);
+  dv= o->internalRep.otherValuePtr;
+  assoc= dv->assoc;
+  idds= assoc->idds;
+
+  snprintf(buf,sizeof(buf), "%d", dv->ix);
   obj_updatestr_vstringls(o,
-                         prefix, strlen(prefix),
+                         idds->valprefix, strlen(idds->valprefix),
                          buf, strlen(buf),
                          (char*)0);
 }
index 696583a..98c6cd9 100644 (file)
@@ -14,7 +14,7 @@ Fini maskmapv                 fini_somethingv(ip, rc, &@.sth);
 Type sockaddr:                 SockAddr_Value @
 Init sockaddr                  sockaddr_clear(&@);
 
-Type iddata(IdDataTable *tab): void *@
+Type iddata(const IdDataSpec *idds):   void *@
 Type ulong:                    uint32_t @
 Type long:                     long @
 Type string:                   const char *@
index 08f5f45..ff16917 100644 (file)
@@ -21,8 +21,6 @@ typedef struct DgramSocket {
   int addr_buflen, msg_buflen;
 } DgramSocket;
 
-IdDataTable dgram_socks= { "dgramsock" };
-
 int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip,
                           SockAddr_Value local, void **sock_r) {
   int fd, al, r;
@@ -152,14 +150,24 @@ int do_dgram_socket_on_receive(ClientData cd, Tcl_Interp *ip,
   return TCL_OK;
 }
 
-int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, void *sock_v) {
-  DgramSocket *sock= sock_v;
-
+static void destroy(DgramSocket *sock) {
   cancel(sock);
   close(sock->fd); /* nothing useful to be done with errors */
-  tabledataid_disposing(sock,&dgram_socks);
   TFREE(sock->addr_buf);
   TFREE(sock->msg_buf);
   TFREE(sock);
+}
+
+static void destroy_idtabcb(Tcl_Interp *ip, void *sock_v) {
+  destroy(sock_v);
+}
+
+int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, void *sock_v) {
+  destroy(sock_v);
+  tabledataid_disposing(ip,sock_v,&dgram_socks);
   return TCL_OK;
 }
+
+const IdDataSpec dgram_socks= {
+  "dgramsock", "dgramsock-table", destroy_idtabcb
+};
index 2b03287..b49301f 100644 (file)
@@ -215,10 +215,9 @@ void scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj **argv);
 /* from idtable.c */
 
 typedef struct {
-  const char *const prefix;
-  int n;
-  void **a;
-} IdDataTable;
+  const char *valprefix, *assockey;
+  void (*destroyitem)(Tcl_Interp *ip, void *val);
+} IdDataSpec;
 
 /* The stored struct must start with a single int, conventionally
  * named `ix'.  When the struct is returned for the first time ix must
@@ -226,10 +225,10 @@ typedef struct {
  * the struct is registered by the iddatatable machinery. */
 
 extern Tcl_ObjType tabledataid_nearlytype;
-int tabledataid_parse(Tcl_Interp *ip, Tcl_Obj *o, IdDataTable *tab);
-void tabledataid_disposing(void *val, IdDataTable *tab);
+int tabledataid_parse(Tcl_Interp *ip, Tcl_Obj *o, const IdDataSpec *idds);
+void tabledataid_disposing(Tcl_Interp *ip, void *val, const IdDataSpec *idds);
   /* call this when you destroy the struct, to remove its name;
-   * _disposing is idempotent*/
+   * _disposing is idempotent */
 
 /* from adns.c */
 
@@ -238,16 +237,16 @@ typedef struct {
   adns_rrtype number;
 } AdnsTclRRTypeInfo;
 
-extern IdDataTable adnstcl_queries, adnstcl_resolvers;
+extern const IdDataSpec adnstcl_queries, adnstcl_resolvers;
 
 /* from dgram.c */
 
-extern IdDataTable dgram_socks;
+extern const IdDataSpec dgram_socks;
 int newfdposixerr(Tcl_Interp *ip, int fd, const char *m);
 
 /* from tuntap.c */
 
-extern IdDataTable tuntap_socks;
+extern const IdDataSpec tuntap_socks;
 
 /* from hook.c */
 
index 7a1d268..f45b3c9 100644 (file)
@@ -26,8 +26,6 @@ typedef struct TunSocket {
   char *ifname;
 } TuntapSocket;
 
-IdDataTable tuntap_socks= { "tuntap" };
-
 int do_tuntap_socket_raw_create(ClientData cd, Tcl_Interp *ip,
                                const char *ifname, void **sock_r) {
   int fd, r;
@@ -142,15 +140,24 @@ int do_tuntap_socket_raw_on_transmit(ClientData cd, Tcl_Interp *ip,
   return TCL_OK;
 }
 
-int do_tuntap_socket_raw_close(ClientData cd, Tcl_Interp *ip, void *sock_v) {
+static void destroy(void *sock_v) {
   TuntapSocket *sock= sock_v;
-  
-  int sockix;
   cancel(sock);
   close(sock->fd); /* nothing useful to be done with errors */
-  sockix= sock->ix;
   TFREE(sock->msg_buf);
   TFREE(sock);
-  tuntap_socks.a[sockix]= 0;
+}
+
+static void destroy_idtabcb(Tcl_Interp *ip, void *sock_v) {
+  destroy(sock_v);
+}
+
+int do_tuntap_socket_raw_close(ClientData cd, Tcl_Interp *ip, void *sock) {
+  destroy(sock);
+  tabledataid_disposing(ip,sock,&tuntap_socks);
   return TCL_OK;
 }
+
+const IdDataSpec tuntap_socks= {
+  "tuntap", "tuntap-table", destroy_idtabcb
+};