chiark / gitweb /
new socket id arrangements, working on tun
[chiark-tcl.git] / dgram / dgram.c
index e541a3a2ed5891c687696d7bae982f4d18668d76..81487921b7cbca3900d7d66f6734bb9ed671b71d 100644 (file)
 #include "hbytes.h"
 
 typedef struct DgramSocket {
-  int ix, fd, script_llength;
+  int ix; /* first ! */
+  int fd, script_llength;
   Tcl_Interp *ip;
   Tcl_Obj *script;
   void *addr_buf, *msg_buf;
   int addr_buflen, msg_buflen;
 } DgramSocket;
 
-static int n_socks;
-static DgramSocket **socks;
-
-static int sockfail(Tcl_Interp *ip, int fd, const char *m) {
-  int e;
-  e= errno;
-  close(fd);
-  return posixerr(ip,e,m);
-}
+IdDataTable dgram_socks= { "dgramsock" };
 
 int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip,
-                         SockAddr_Value local, DgramSockID *sock_r) {
-  int fd, al, r, sockix;
+                          SockAddr_Value local, void **sock_r) {
+  int fd, al, r;
   DgramSocket *sock;
   const struct sockaddr *sa;
 
-  for (sockix=0; sockix<n_socks && socks[sockix]; sockix++);
-  if (sockix>=n_socks) {
-    n_socks += 2;
-    n_socks *= 2;
-    socks= (void*)Tcl_Realloc((void*)socks, n_socks*sizeof(*socks));
-    while (sockix<n_socks) socks[sockix++]=0;
-    sockix--;
-  }
-
   sa= sockaddr_addr(&local);
   al= sockaddr_len(&local);
 
   fd= socket(sa->sa_family, SOCK_DGRAM, 0);
   if (fd<0) return posixerr(ip,errno,"socket");
-  r= bind(fd, sa, al);  if (r) return sockfail(ip,fd,"bind");
-  r= setnonblock(fd, 1);  if (r) return sockfail(ip,fd,"setnonblock");
+  r= bind(fd, sa, al);  if (r) return newfdposixerr(ip,fd,"bind");
+  r= setnonblock(fd, 1);  if (r) return newfdposixerr(ip,fd,"setnonblock");
 
-  socks[sockix]= sock= TALLOC(sizeof(DgramSocket));
+  sock= TALLOC(sizeof(DgramSocket));
+  sock->ix= -1;
   sock->fd= fd;
-  sock->ix= sockix;
   sock->script= 0;
   sock->addr_buflen= al+1;
   sock->addr_buf= TALLOC(sock->addr_buflen);
@@ -67,8 +51,9 @@ int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip,
 }
 
 int do_dgram_socket_transmit(ClientData cd, Tcl_Interp *ip,
-                            DgramSocket *sock, HBytes_Value data,
+                            void *sock_v, HBytes_Value data,
                             SockAddr_Value remote) {
+  DgramSocket *sock= sock_v;
   int l, r;
 
   r= sendto(sock->fd,
@@ -139,7 +124,7 @@ static void recv_call(ClientData sock_cd, int mask) {
 
   args[0]= ret_hb(ip, message_val);  hbytes_empty(&message_val);
   args[1]= ret_sockaddr(ip, peer_val);  sockaddr_clear(&peer_val);
-  args[2]= ret_sockid(ip, sock);
+  args[2]= ret_iddata(ip, sock, &dgram_socks);
   for (i=0; i<3; i++) Tcl_IncrRefCount(args[i]);
 
   invoke= Tcl_DuplicateObj(sock->script);
@@ -159,7 +144,8 @@ x_rc:
 }
 
 int do_dgram_socket_on_receive(ClientData cd, Tcl_Interp *ip,
-                              DgramSocket *sock, Tcl_Obj *script) {
+                              void *sock_v, Tcl_Obj *script) {
+  DgramSocket *sock= sock_v;
   int rc;
   
   if (script) {
@@ -177,7 +163,8 @@ int do_dgram_socket_on_receive(ClientData cd, Tcl_Interp *ip,
   return TCL_OK;
 }
 
-int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, DgramSocket *sock) {
+int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, void *sock_v) {
+  DgramSocket *sock= sock_v;
   int sockix;
   cancel(sock);
   close(sock->fd); /* nothing useful to be done with errors */
@@ -185,73 +172,6 @@ int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, DgramSocket *sock) {
   TFREE(sock->addr_buf);
   TFREE(sock->msg_buf);
   TFREE(sock);
-  socks[sockix]= 0;
-  return TCL_OK;
-}
-
-/* Arg parsing */
-
-int pat_sockid(Tcl_Interp *ip, Tcl_Obj *o, DgramSocket **val) {
-  int rc, sockix;
-  DgramSocket *sock;
-  
-  rc= Tcl_ConvertToType(ip,o,&dgramsockid_type);
-  if (rc) return rc;
-
-  sockix= o->internalRep.longValue;
-  if (sockix >= n_socks || !(sock= socks[sockix]))
-    return staticerr(ip,"dgram socket not open",0);
-
-  assert(socks[sockix]->ix == sockix);
-
-  *val= sock;
-  return TCL_OK;
-}
-
-Tcl_Obj *ret_sockid(Tcl_Interp *ip, DgramSocket *val) {
-  Tcl_Obj *o;
-
-  o= Tcl_NewObj();
-  Tcl_InvalidateStringRep(o);
-  o->internalRep.longValue= val->ix;
-  o->typePtr= &dgramsockid_type;
-  return o;
-}
-
-static void sockid_t_free(Tcl_Obj *o) { }
-
-static void sockid_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
-  dup->internalRep= src->internalRep;
-  dup->typePtr= &dgramsockid_type;
-}
-
-static void sockid_t_ustr(Tcl_Obj *o) {
-  char buf[75];
-
-  snprintf(buf,sizeof(buf), "%d", (int)o->internalRep.longValue);
-  obj_updatestr_vstringls(o,
-                         "dgramsock",9,
-                         buf, strlen(buf),
-                         (char*)0);
-}
-
-static int sockid_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
-  unsigned long ul;
-  char *ep, *str;
-  
-  str= Tcl_GetStringFromObj(o,0);
-  if (memcmp(str,"dgramsock",9)) return staticerr(ip,"bad dgram socket id",0);
-  errno=0; ul=strtoul(str+9,&ep,10);
-  if (errno || *ep) return staticerr(ip,"bad dgram socket id number",0);
-  if (ul > INT_MAX) return staticerr(ip,"out of range dgram socket id",0);
-
-  objfreeir(o);
-  o->internalRep.longValue= ul;
-  o->typePtr= &dgramsockid_type;
+  dgram_socks.a[sockix]= 0;
   return TCL_OK;
 }
-
-Tcl_ObjType dgramsockid_type = {
-  "dgramsockid",
-  sockid_t_free, sockid_t_dup, sockid_t_ustr, sockid_t_sfa
-};