chiark / gitweb /
Socket address stuff. Sockid is broken still.
authorian <ian>
Sat, 7 Sep 2002 00:59:57 +0000 (00:59 +0000)
committerian <ian>
Sat, 7 Sep 2002 00:59:57 +0000 (00:59 +0000)
15 files changed:
base/chiark-tcl.h
base/hook.c
base/parse.c
base/tables-examples.tct
base/troglodyte-Makefile
crypto/bcmode.c
crypto/crypto.c
dgram/dgram.c [new file with mode: 0644]
dgram/misc.c
dgram/sockaddr.c [new file with mode: 0644]
hbytes/chop.c
hbytes/hbytes.c
hbytes/hbytes.h
hbytes/hook.c
hbytes/parse.c

index 86b2dba..951ae12 100644 (file)
 
 #include <assert.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
 
 #include <tcl.h>
 
@@ -35,6 +41,8 @@ typedef unsigned char Byte;
 
 /* from hbytes.c */
 
+int Hbytes_Init(Tcl_Interp *ip); /* called by Tcl's "load" */
+
 /* Internal representation details: */
 #define HBYTES_ISEMPTY(hb)    (!(hb)->begin_complex && !(hb)->end_0)
 #define HBYTES_ISSENTINEL(hb) (!(hb)->begin_complex && (hb)->end_0)
@@ -88,13 +96,35 @@ void hbytes_free(const HBytes_Value *frees);
 /* The value made by hbytes_sentinel should not be passed to
  * anything except HBYTES_IS..., and hbytes_free. */
 
+/* from sockaddr.c */
+
+typedef struct {
+  Byte *begin, *end;
+} SockAddr_Value;
+
+extern Tcl_ObjType sockaddr_type;
+
+void sockaddr_clear(SockAddr_Value*);
+void sockaddr_create(SockAddr_Value*, const struct sockaddr *addr, int len);
+int sockaddr_len(const SockAddr_Value*);
+const struct sockaddr *sockaddr_addr(const SockAddr_Value*);
+void sockaddr_free(const SockAddr_Value*);
+
+/* from dgram.c */
+
+extern Tcl_ObjType sockid_type;
+
 /* from hook.c */
 
 int staticerr(Tcl_Interp *ip, const char *m);
+int posixerr(Tcl_Interp *ip, int errnoval, const char *m);
 void objfreeir(Tcl_Obj *o);
-void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
 int get_urandom(Tcl_Interp *ip, Byte *buffer, int l);
 
+void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+                               int l, const char *prefix);
+
 /* from parse.c */
 
 typedef struct {
@@ -187,9 +217,14 @@ typedef struct {
 
 extern const BlockCipherModeInfo blockciphermodeinfos[];
 
+/* from misc.c */
+
+int setnonblock(int fd, int isnonblock);
+
 /* useful macros */
 
 #define OBJ_HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue)
+#define OBJ_SOCKADDR(o) ((SockAddr_Value*)&(o)->internalRep.twoPtrValue)
 
 #define TALLOC(s) ((void*)Tcl_Alloc((s)))
 #define TFREE(f) (Tcl_Free((void*)(f)))
index b6c0c9e..e53af08 100644 (file)
@@ -71,11 +71,18 @@ static void hbytes_t_free(Tcl_Obj *o) {
   hbytes_free(OBJ_HBYTES(o));
 }
 
-void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+                               int l, const char *prefix) {
   char *str;
+  int pl;
+
+  pl= strlen(prefix);
+  o->length= l*2+pl;
+  str= o->bytes= TALLOC(o->length+1);
+  
+  memcpy(str,prefix,pl);
+  str += pl;
 
-  str= o->bytes= TALLOC(l*2+1);
-  o->length= l*2;
   while (l>0) {
     sprintf(str,"%02x",*byte);
     str+=2; byte++; l--;
@@ -83,6 +90,10 @@ void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
   *str= 0;
 }
 
+void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+  obj_updatestr_array_prefix(o,byte,l,"");
+}
+
 static void hbytes_t_ustr(Tcl_Obj *o) {
   obj_updatestr_array(o,
                      hbytes_data(OBJ_HBYTES(o)),
@@ -172,6 +183,12 @@ int do__hbytes(ClientData cd, Tcl_Interp *ip,
   return subcmd->func(0,ip,objc,objv);
 }
 
+int do__dgram_socket(ClientData cd, Tcl_Interp *ip,
+                    const DgramSocket_SubCommand *subcmd,
+                    int objc, Tcl_Obj *const *objv) {
+  return subcmd->func(0,ip,objc,objv);
+}
+
 #define URANDOM "/dev/urandom"
 
 int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) {
@@ -202,6 +219,9 @@ int Hbytes_Init(Tcl_Interp *ip) {
   Tcl_RegisterObjType(&blockcipherkey_type);
   Tcl_RegisterObjType(&enum_nearlytype);
   Tcl_RegisterObjType(&enum1_nearlytype);
-  Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0);
+  Tcl_RegisterObjType(&sockaddr_type);
+  Tcl_RegisterObjType(&sockid_type);
+  Tcl_CreateObjCommand(ip, "hbytes",       pa__hbytes,       0,0);
+  Tcl_CreateObjCommand(ip, "dgram-socket", pa__dgram_socket, 0,0);
   return TCL_OK;
 }
index ddb5ac5..b81511c 100644 (file)
@@ -42,9 +42,7 @@ int pat_hbv(Tcl_Interp *ip, Tcl_Obj *var, HBytes_Var *agg) {
   rc= Tcl_ConvertToType(ip,val,&hbytes_type);
   if (rc) return rc;
 
-  agg->hb= OBJ_HBYTES(val);
-  return TCL_OK;
-}
+  agg->hb= OBJ_HBYTES(val); return TCL_OK; }
 
 void fini_hbv(Tcl_Interp *ip, int rc, HBytes_Var *agg) {
   Tcl_Obj *ro;
index b40198f..5814334 100644 (file)
@@ -1,15 +1,25 @@
 Type hb:                       HBytes_Value @
 Init hb                                hbytes_sentinel(&@);
+
 Type hbv:                      HBytes_Var @
 Init hbv                       @.hb=0; @.obj=0; @.var=0;
 Fini hbv                       fini_hbv(ip, rc, &@);
 
+Type sockaddr:                 SockAddr_Value @
+Init sockaddr                  sockaddr_clear(&@);
+
+Type sockid:                   int @
+Init sockid                    @=-1;
+
 H-Include      "hbytes.h"
 
 Untabled
        hbytes
                subcmd  enum(HBytes_SubCommand, "hbytes subcommand")
                obj     ...
+       dgram-socket
+               subcmd enum(DgramSocket_SubCommand,"dgram-socket subcommand")
+               obj     ...
 
 Table hbytes HBytes_SubCommand
        raw2h
@@ -75,6 +85,9 @@ Table hbytes HBytes_SubCommand
                length  int
                =>      hb
 
-#Table udp UDP_SubCommand
-#      create
-#
+Table dgram_socket DgramSocket_SubCommand
+       create
+               local   sockaddr
+               =>      sockid
+#      transmit
+#              
index 9794ba4..64160c0 100644 (file)
@@ -1,9 +1,12 @@
 OBJS=          tables.o \
                hbytes.o \
                enum.o \
+               sockaddr.o \
+               dgram.o \
                chop.o \
                hook.o \
                bcmode.o \
+               misc.o \
                algtables.o \
                serpent.o \
                sha1.o \
@@ -21,7 +24,8 @@ AUTOS=                $(AUTO_HDRS) $(AUTO_SRCS)
 TARGETS=       hbytes.so
 
 CC_CRYPTO=     $(CC) $(CFLAGS) $(CPPFLAGS) -O3
-CFLAGS=                -g -Wall $(OPTIMISE)
+CFLAGS=                -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror \
+               $(OPTIMISE)
 OPTIMISE=      -O2
 
 all:           $(TARGETS) $(AUTOS)
index a40aff0..f7c808d 100644 (file)
@@ -3,10 +3,10 @@
   
 #include "hbytes.h"
 
-const char *mode_cbc_encrypt(Byte *data, int blocks,
-                            const Byte *iv, Byte *chain,
-                            const BlockCipherAlgInfo *alg, int encr,
-                            int blocksize, const void *sch) {
+static const char *mode_cbc_encrypt(Byte *data, int blocks,
+                                   const Byte *iv, Byte *chain,
+                                   const BlockCipherAlgInfo *alg, int encr,
+                                   int blocksize, const void *sch) {
   memcpy(chain,iv,blocksize);
   alg->byteswap(chain);
   
@@ -23,10 +23,10 @@ const char *mode_cbc_encrypt(Byte *data, int blocks,
   return 0;
 }
 
-const char *mode_cbc_decrypt(Byte *data, int blocks,
-                            const Byte *iv, Byte *chain,
-                            const BlockCipherAlgInfo *alg, int encr,
-                            int blocksize, const void *sch) {
+static const char *mode_cbc_decrypt(Byte *data, int blocks,
+                                   const Byte *iv, Byte *chain,
+                                   const BlockCipherAlgInfo *alg, int encr,
+                                   int blocksize, const void *sch) {
   int cchain= 0;
 
   memcpy(chain,iv,blocksize);
@@ -46,10 +46,10 @@ const char *mode_cbc_decrypt(Byte *data, int blocks,
   return 0;
 }
 
-const char *mode_ecb(Byte *data, int blocks,
-                    const Byte *iv, Byte *chain,
-                    const BlockCipherAlgInfo *alg, int encr,
-                    int blocksize, const void *sch) {
+static const char *mode_ecb(Byte *data, int blocks,
+                           const Byte *iv, Byte *chain,
+                           const BlockCipherAlgInfo *alg, int encr,
+                           int blocksize, const void *sch) {
   while (blocks > 0) {
     alg->byteswap(data);
     (encr ? &alg->encrypt : &alg->decrypt)->crypt(sch, data, data);
index 7cc2914..ec6a6de 100644 (file)
@@ -133,8 +133,8 @@ Tcl_ObjType blockcipherkey_type = {
   key_t_free, key_t_dup, key_t_ustr, key_t_sfa
 };
 
-CiphKeyValue *get_key(Tcl_Interp *ip, Tcl_Obj *key_obj,
-                     const void *alg, int want_bufferslen) {
+static CiphKeyValue *get_key(Tcl_Interp *ip, Tcl_Obj *key_obj,
+                            const void *alg, int want_bufferslen) {
   CiphKeyValue *key;
   int rc;
   
diff --git a/dgram/dgram.c b/dgram/dgram.c
new file mode 100644 (file)
index 0000000..ecdd2f7
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ */
+/*
+ * dgram-socket create <local>                        => <sockid>
+ * dgram-socket close <sockid>
+ * dgram-socket transmit <sockid> <data> <remote>
+ * dgram-socket on-receive <sockid> <script>
+ *    calls, effectively,  eval <script> [list <data> <remote-addr> <socket>]
+ */
+
+#include "tables.h"
+#include "hbytes.h"
+
+static int sockfail(Tcl_Interp *ip, int fd, const char *m) {
+  int e;
+  e= errno;
+  close(fd);
+  return posixerr(ip,e,m);
+}
+
+int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip,
+                         SockAddr_Value local, int *result) {
+  int fd, al, r;
+  const struct sockaddr *sa;
+
+  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");
+  *result= fd;
+  return TCL_OK;
+}
+
+/* Arg parsing */
+
+int pat_sockid(Tcl_Interp *ip, Tcl_Obj *o, int *val) {
+  int rc;
+  
+  rc= Tcl_ConvertToType(ip,o,&sockid_type);
+  if (rc) return rc;
+
+  *val= o->internalRep.longValue;
+  return TCL_OK;
+}
+
+Tcl_Obj *ret_sockid(Tcl_Interp *ip, int val) {
+  Tcl_Obj *o;
+
+  o= Tcl_NewObj();
+  Tcl_InvalidateStringRep(o);
+  o->internalRep.longValue= val;
+  o->typePtr= &sockid_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;
+}
+
+static void sockid_t_ustr(Tcl_Obj *o) {
+  char buf[100];
+  int l;
+
+  snprintf(buf,sizeof(buf),"dgramsock%d", (int)o->internalRep.longValue);
+  l= o->length= strlen(buf);
+  o->bytes= TALLOC(l+1);
+  strcpy(o->bytes, buf);
+}
+
+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");
+  errno=0; ul=strtoul(str+9,&ep,10);
+  if (errno || *ep) return staticerr(ip,"bad dgram socket id number");
+  if (ul > INT_MAX) return staticerr(ip,"out of range dgram socket id");
+  o->internalRep.longValue= ul;
+  return TCL_OK;
+}
+
+Tcl_ObjType sockid_type = {
+  "sockid-nearly",
+  sockid_t_free, sockid_t_dup, sockid_t_ustr, sockid_t_sfa
+};
index 1d37020..8c36554 100644 (file)
@@ -1,6 +1,6 @@
 /**/
 
-#include "all.h"
+#include "hbytes.h"
 
 int setnonblock(int fd, int isnonblock) {
   int r;
diff --git a/dgram/sockaddr.c b/dgram/sockaddr.c
new file mode 100644 (file)
index 0000000..bedc109
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * struct sockaddr
+ *
+ * syntaxes:
+ *    ddd.ddd.ddd.ddd,nnnn       IPv4 address and port
+ *                                 ... host or port may be `*'
+ *    /abs/path/to/socket        AF_UNIX
+ *    ./rel/path/to/socket       AF_UNIX
+ */
+
+#include "hbytes.h"
+#include "tables.h"
+
+#define SOCKADDR_LEN(sa) ((sa)->end - (sa)->begin)
+
+/* parsing */
+
+int pat_sockaddr(Tcl_Interp *ip, Tcl_Obj *o, SockAddr_Value *val) {
+  int rc;
+
+  rc= Tcl_ConvertToType(ip,o,&sockaddr_type);
+  if (rc) return rc;
+
+  *val= *OBJ_SOCKADDR(o);
+  return TCL_OK;
+}
+  
+Tcl_Obj *ret_sockaddr(Tcl_Interp *ip, SockAddr_Value val) {
+  Tcl_Obj *o;
+
+  o= Tcl_NewObj();
+  Tcl_InvalidateStringRep(o);
+  *OBJ_SOCKADDR(o)= val;
+  o->typePtr= &sockaddr_type;
+  return o;
+}
+
+/* native type methods */
+
+void sockaddr_clear(SockAddr_Value *v) { v->begin= v->end= 0; }
+
+void sockaddr_create(SockAddr_Value *v, const struct sockaddr *addr, int len) {
+  Byte *begin;
+  
+  v->begin= begin= TALLOC(len);
+  memcpy(begin, addr, len);
+  v->end= begin + len;
+}  
+
+int sockaddr_len(const SockAddr_Value *v) {
+  return SOCKADDR_LEN(v);
+}
+
+const struct sockaddr *sockaddr_addr(const SockAddr_Value *v) {
+  return (const void*)v->begin;
+}
+  
+void sockaddr_free(const SockAddr_Value *v) {
+  TFREE(v->begin);
+}
+
+/* Sockaddr Tcl type */
+
+static void sockaddr_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
+  objfreeir(dup);
+  sockaddr_create(OBJ_SOCKADDR(dup),
+                 sockaddr_addr(OBJ_SOCKADDR(src)),
+                 sockaddr_len(OBJ_SOCKADDR(src)));
+}
+
+static void sockaddr_t_free(Tcl_Obj *o) {
+  sockaddr_free(OBJ_SOCKADDR(o));
+}
+
+static void sockaddr_t_ustr(Tcl_Obj *o) {
+  const struct sockaddr *sa;
+  char i46buf[INET6_ADDRSTRLEN];
+  int al, sl, pl;
+  const char *string, *prepend;
+  
+  sa= sockaddr_addr(OBJ_SOCKADDR(o));
+  al= sockaddr_len(OBJ_SOCKADDR(o));
+    
+  switch (sa->sa_family) {
+  case AF_INET:
+  case AF_INET6:
+    assert(sizeof(i46buf) >= INET_ADDRSTRLEN);
+    assert(al >= sizeof(struct sockaddr_in));
+    inet_ntop(sa->sa_family, sa, i46buf, al);
+    string= i46buf;
+    prepend= "";
+    break;
+
+  case AF_UNIX:
+    assert(al >= sizeof(struct sockaddr_un));
+    string= ((const struct sockaddr_un*)sa)->sun_path;
+    prepend= "";
+    if (!string[0]) string="//"; 
+    else if (string[0] != '/' || string[1] == '/') prepend= "./"; 
+
+  default: /* ouch ! */
+    obj_updatestr_array_prefix(o,(const void*)sa,al,"?");
+    return;
+  }
+
+  pl= strlen(prepend);
+  sl= strlen(string);
+  o->bytes= TALLOC(sl+1);
+  memcpy(o->bytes, prepend, pl);
+  memcpy(o->bytes+pl, string, sl+1);
+}
+
+static int sockaddr_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
+  union {
+    struct sockaddr_un sun;
+    struct sockaddr_in sin;
+  } s;
+  unsigned long port_l;
+  
+  char *str, *ep, *copy;
+  int sl, pl, iprv;
+  const char *comma, *path;
+
+  str= Tcl_GetStringFromObj(o,0);  assert(str);
+  objfreeir(o);
+  memset(&s,0,sizeof(s));
+
+  if (str[0]=='/' || (str[0]=='.' && str[1]=='/')) {
+    
+    sl= sizeof(s.sun);
+    s.sun.sun_family= AF_UNIX;
+
+    if (strcmp(str,"//")) path= "";
+    else if (memcmp(str,"./",2) && str[2]) path= str+2;
+    else { assert(str[0]=='/' && str[1]!='/'); path=str; }
+
+    if (strlen(str) >= sizeof(s.sun.sun_path))
+      return staticerr(ip, "AF_UNIX path too long");
+
+    strcpy(s.sun.sun_path, str);
+
+  } else if ((comma= strchr(str, ','))) {
+
+    sl= sizeof(s.sin);
+    s.sin.sin_family= AF_INET;
+
+    pl= comma - str;
+    copy= TALLOC(pl+1);
+    memcpy(copy, str, pl);
+    copy[pl]= 0;
+
+    if (!strcmp(copy,"*")) {
+      s.sin.sin_addr.s_addr= INADDR_ANY;
+      iprv= 1;
+    } else {
+      iprv= inet_pton(AF_INET, copy, &s.sin.sin_addr);
+    }
+    TFREE(copy);
+
+    if (!iprv) return staticerr(ip, "bad IPv4 address syntax");
+
+    comma++;
+    if (!strcmp(comma,"*")) {
+      s.sin.sin_port= 0;
+    } else {
+      errno=0; port_l=strtoul(comma,&ep,10);
+      if (errno || *ep) return staticerr(ip, "bad IPv4 port");
+      if (port_l > 65535) return staticerr(ip, "IPv4 port out of range");
+      s.sin.sin_port= htons(port_l);
+    }
+
+  } else {
+
+    return staticerr(ip, "bad socket address syntax");
+
+  }
+
+  sockaddr_create(OBJ_SOCKADDR(o), (void*)&s, sl);
+  
+  o->typePtr = &sockaddr_type;
+  return TCL_OK;
+}
+
+Tcl_ObjType sockaddr_type = {
+  "sockaddr",
+  sockaddr_t_free, sockaddr_t_dup, sockaddr_t_ustr, sockaddr_t_sfa
+};
index c81e5d6..48eb770 100644 (file)
@@ -4,6 +4,7 @@
 #include <string.h>
 
 #include "hbytes.h"
+#include "tables.h"
 
 static int strs1(Tcl_Interp *ip, int strc, Tcl_Obj *const *strv, int *l_r) {
   int rc, l, i;
index 6bb86c3..b941937 100644 (file)
@@ -121,7 +121,8 @@ Byte *hbytes_append(HBytes_Value *hb, int el) {
   return newpart;
 }
 
-HBytes_ComplexValue *prechop(HBytes_Value *hb, int cl, const Byte **rv) {
+static HBytes_ComplexValue*
+prechop(HBytes_Value *hb, int cl, const Byte **rv) {
   HBytes_ComplexValue *cx;
 
   if (cl<0) { *rv=0; return 0; }
index 86b2dba..951ae12 100644 (file)
 
 #include <assert.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
 
 #include <tcl.h>
 
@@ -35,6 +41,8 @@ typedef unsigned char Byte;
 
 /* from hbytes.c */
 
+int Hbytes_Init(Tcl_Interp *ip); /* called by Tcl's "load" */
+
 /* Internal representation details: */
 #define HBYTES_ISEMPTY(hb)    (!(hb)->begin_complex && !(hb)->end_0)
 #define HBYTES_ISSENTINEL(hb) (!(hb)->begin_complex && (hb)->end_0)
@@ -88,13 +96,35 @@ void hbytes_free(const HBytes_Value *frees);
 /* The value made by hbytes_sentinel should not be passed to
  * anything except HBYTES_IS..., and hbytes_free. */
 
+/* from sockaddr.c */
+
+typedef struct {
+  Byte *begin, *end;
+} SockAddr_Value;
+
+extern Tcl_ObjType sockaddr_type;
+
+void sockaddr_clear(SockAddr_Value*);
+void sockaddr_create(SockAddr_Value*, const struct sockaddr *addr, int len);
+int sockaddr_len(const SockAddr_Value*);
+const struct sockaddr *sockaddr_addr(const SockAddr_Value*);
+void sockaddr_free(const SockAddr_Value*);
+
+/* from dgram.c */
+
+extern Tcl_ObjType sockid_type;
+
 /* from hook.c */
 
 int staticerr(Tcl_Interp *ip, const char *m);
+int posixerr(Tcl_Interp *ip, int errnoval, const char *m);
 void objfreeir(Tcl_Obj *o);
-void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
 int get_urandom(Tcl_Interp *ip, Byte *buffer, int l);
 
+void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+                               int l, const char *prefix);
+
 /* from parse.c */
 
 typedef struct {
@@ -187,9 +217,14 @@ typedef struct {
 
 extern const BlockCipherModeInfo blockciphermodeinfos[];
 
+/* from misc.c */
+
+int setnonblock(int fd, int isnonblock);
+
 /* useful macros */
 
 #define OBJ_HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue)
+#define OBJ_SOCKADDR(o) ((SockAddr_Value*)&(o)->internalRep.twoPtrValue)
 
 #define TALLOC(s) ((void*)Tcl_Alloc((s)))
 #define TFREE(f) (Tcl_Free((void*)(f)))
index b6c0c9e..e53af08 100644 (file)
@@ -71,11 +71,18 @@ static void hbytes_t_free(Tcl_Obj *o) {
   hbytes_free(OBJ_HBYTES(o));
 }
 
-void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+                               int l, const char *prefix) {
   char *str;
+  int pl;
+
+  pl= strlen(prefix);
+  o->length= l*2+pl;
+  str= o->bytes= TALLOC(o->length+1);
+  
+  memcpy(str,prefix,pl);
+  str += pl;
 
-  str= o->bytes= TALLOC(l*2+1);
-  o->length= l*2;
   while (l>0) {
     sprintf(str,"%02x",*byte);
     str+=2; byte++; l--;
@@ -83,6 +90,10 @@ void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
   *str= 0;
 }
 
+void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+  obj_updatestr_array_prefix(o,byte,l,"");
+}
+
 static void hbytes_t_ustr(Tcl_Obj *o) {
   obj_updatestr_array(o,
                      hbytes_data(OBJ_HBYTES(o)),
@@ -172,6 +183,12 @@ int do__hbytes(ClientData cd, Tcl_Interp *ip,
   return subcmd->func(0,ip,objc,objv);
 }
 
+int do__dgram_socket(ClientData cd, Tcl_Interp *ip,
+                    const DgramSocket_SubCommand *subcmd,
+                    int objc, Tcl_Obj *const *objv) {
+  return subcmd->func(0,ip,objc,objv);
+}
+
 #define URANDOM "/dev/urandom"
 
 int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) {
@@ -202,6 +219,9 @@ int Hbytes_Init(Tcl_Interp *ip) {
   Tcl_RegisterObjType(&blockcipherkey_type);
   Tcl_RegisterObjType(&enum_nearlytype);
   Tcl_RegisterObjType(&enum1_nearlytype);
-  Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0);
+  Tcl_RegisterObjType(&sockaddr_type);
+  Tcl_RegisterObjType(&sockid_type);
+  Tcl_CreateObjCommand(ip, "hbytes",       pa__hbytes,       0,0);
+  Tcl_CreateObjCommand(ip, "dgram-socket", pa__dgram_socket, 0,0);
   return TCL_OK;
 }
index ddb5ac5..b81511c 100644 (file)
@@ -42,9 +42,7 @@ int pat_hbv(Tcl_Interp *ip, Tcl_Obj *var, HBytes_Var *agg) {
   rc= Tcl_ConvertToType(ip,val,&hbytes_type);
   if (rc) return rc;
 
-  agg->hb= OBJ_HBYTES(val);
-  return TCL_OK;
-}
+  agg->hb= OBJ_HBYTES(val); return TCL_OK; }
 
 void fini_hbv(Tcl_Interp *ip, int rc, HBytes_Var *agg) {
   Tcl_Obj *ro;