From ed7354bcb695fcf3ee3f5cea14be209fbb99f161 Mon Sep 17 00:00:00 2001 From: ian Date: Thu, 26 Dec 2002 13:08:33 +0000 Subject: [PATCH] scriptinv --- base/chiark-tcl.h | 15 +++++++++ base/scriptinv.c | 53 +++++++++++++++++++++++++++++++ base/tables-examples.tct | 8 ++--- base/troglodyte-Makefile | 1 + dgram/dgram.c | 53 +++++++++++++------------------ hbytes/hbytes.h | 15 +++++++++ tuntap/tuntap.c | 68 +++++++++++++++++++++++----------------- 7 files changed, 147 insertions(+), 66 deletions(-) create mode 100644 base/scriptinv.c diff --git a/base/chiark-tcl.h b/base/chiark-tcl.h index f7d0110..484f10d 100644 --- a/base/chiark-tcl.h +++ b/base/chiark-tcl.h @@ -175,6 +175,21 @@ int sockaddr_len(const SockAddr_Value*); const struct sockaddr *sockaddr_addr(const SockAddr_Value*); void sockaddr_free(const SockAddr_Value*); +/* from scriptinv.c */ + +typedef struct { /* semi-opaque - read only, and then only where commented */ + Tcl_Interp *ip; /* valid, non-0 and useable if set */ + Tcl_Obj *obj; /* non-0 iff set (but only test for 0/non-0) */ + int llength; +} ScriptToInvoke; + +void scriptinv_init(ScriptToInvoke *si); +int scriptinv_set(ScriptToInvoke *si, Tcl_Interp *ip, Tcl_Obj *newscript); +void scriptinv_cancel(ScriptToInvoke *si); /* then don't invoke */ + /* no separate free function - just cancel */ + +void scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj **argv); + /* from idtable.c */ typedef struct { diff --git a/base/scriptinv.c b/base/scriptinv.c new file mode 100644 index 0000000..b27654e --- /dev/null +++ b/base/scriptinv.c @@ -0,0 +1,53 @@ +/* + */ + +#include "hbytes.h" + +void scriptinv_init(ScriptToInvoke *si) { + si->obj= 0; +} + +void scriptinv_cancel(ScriptToInvoke *si) { + if (si->obj) { + Tcl_DecrRefCount(si->obj); + si->obj= 0; + } +} + +int scriptinv_set(ScriptToInvoke *si, Tcl_Interp *ip, Tcl_Obj *newscript) { + int rc; + + scriptinv_cancel(si); + + rc= Tcl_ListObjLength(ip, newscript, &si->llength); + if (rc) return rc; + + Tcl_IncrRefCount(newscript); + si->obj= newscript; + si->ip= ip; + return 0; +} + +void scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj **argv) { + Tcl_Obj *invoke=0; + int i, rc; + + assert(si->obj); + + for (i=0; iobj); + Tcl_IncrRefCount(invoke); + + rc= Tcl_ListObjReplace(si->ip,invoke,si->llength,0,argc,argv); + for (i=0; iip,invoke,TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); + if (rc) goto x_rc; + + rc= 0; + +x_rc: + if (invoke) Tcl_DecrRefCount(invoke); + if (rc) Tcl_BackgroundError(si->ip); +} diff --git a/base/tables-examples.tct b/base/tables-examples.tct index 82700dc..b98ba5f 100644 --- a/base/tables-examples.tct +++ b/base/tables-examples.tct @@ -24,7 +24,7 @@ Table toplevel TopLevel_Command ... obj tuntap-socket subcmd enum(TunSocket_SubCommand,"tuntap-socket subcommand") - ... obj + ... obj ulong subcmd enum(ULong_SubCommand,"ulong subcommand") ... obj @@ -184,10 +184,7 @@ Table dgram_socket DgramSocket_SubCommand ?script obj Table tuntap_socket TunSocket_SubCommand - create-ptp - local sockaddr - peer sockaddr - mtu long + create ?ifname string => iddata(&tuntap_socks) close @@ -197,6 +194,7 @@ Table tuntap_socket TunSocket_SubCommand => string receive sock iddata(&tuntap_socks) + mtu long data hb on-transmit sock iddata(&tuntap_socks) diff --git a/base/troglodyte-Makefile b/base/troglodyte-Makefile index 8a19442..24f1e13 100644 --- a/base/troglodyte-Makefile +++ b/base/troglodyte-Makefile @@ -2,6 +2,7 @@ OBJS= tables.o \ hbytes.o \ enum.o \ idtable.o \ + scriptinv.o \ ulongs.o \ sockaddr.o \ dgram.o \ diff --git a/dgram/dgram.c b/dgram/dgram.c index 8148792..b2661a4 100644 --- a/dgram/dgram.c +++ b/dgram/dgram.c @@ -14,9 +14,9 @@ typedef struct DgramSocket { int ix; /* first ! */ - int fd, script_llength; + int fd; Tcl_Interp *ip; - Tcl_Obj *script; + ScriptToInvoke script; void *addr_buf, *msg_buf; int addr_buflen, msg_buflen; } DgramSocket; @@ -40,11 +40,11 @@ int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip, sock= TALLOC(sizeof(DgramSocket)); sock->ix= -1; sock->fd= fd; - sock->script= 0; sock->addr_buflen= al+1; sock->addr_buf= TALLOC(sock->addr_buflen); sock->msg_buflen= 0; sock->msg_buf= 0; + scriptinv_init(&sock->script); *sock_r= sock; return TCL_OK; @@ -66,26 +66,24 @@ int do_dgram_socket_transmit(ClientData cd, Tcl_Interp *ip, } static void cancel(DgramSocket *sock) { - if (sock->script) { + if (sock->script.obj) { + scriptinv_cancel(&sock->script); Tcl_DeleteFileHandler(sock->fd); - Tcl_DecrRefCount(sock->script); - sock->script= 0; } } static void recv_call(ClientData sock_cd, int mask) { DgramSocket *sock= (void*)sock_cd; - Tcl_Interp *ip= sock->ip; - int sz, rc, i, peek; + Tcl_Interp *ip= sock->script.ip; + int sz, rc, peek; HBytes_Value message_val; SockAddr_Value peer_val; - Tcl_Obj *args[3], *invoke; + Tcl_Obj *args[3]; struct msghdr mh; struct iovec iov; hbytes_empty(&message_val); sockaddr_clear(&peer_val); - invoke=0; for (i=0; i<3; i++) args[i]=0; mh.msg_iov= &iov; mh.msg_iovlen= 1; @@ -103,7 +101,11 @@ static void recv_call(ClientData sock_cd, int mask) { iov.iov_len= sock->msg_buflen; sz= recvmsg(sock->fd, &mh, peek); - if (sz==-1) { rc=0; goto x_rc; } + if (sz==-1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) rc=0; + else rc= posixerr(ip,errno,"recvmsg"); + goto x_rc; + } assert(mh.msg_namelen < sock->addr_buflen); @@ -125,40 +127,27 @@ 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_iddata(ip, sock, &dgram_socks); - for (i=0; i<3; i++) Tcl_IncrRefCount(args[i]); - - invoke= Tcl_DuplicateObj(sock->script); - Tcl_IncrRefCount(invoke); - - rc= Tcl_ListObjReplace(ip,invoke,sock->script_llength,0,3,args); - for (i=0; i<3; i++) { Tcl_DecrRefCount(args[i]); args[i]= 0; } - if (rc) goto x_rc; - - rc= Tcl_EvalObjEx(ip,invoke,TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); + scriptinv_invoke(&sock->script,3,args); + rc= 0; + x_rc: - if (invoke) Tcl_DecrRefCount(invoke); - if (rc) Tcl_BackgroundError(ip); } int do_dgram_socket_on_receive(ClientData cd, Tcl_Interp *ip, - void *sock_v, Tcl_Obj *script) { + void *sock_v, Tcl_Obj *newscript) { DgramSocket *sock= sock_v; int rc; - if (script) { - rc= Tcl_ListObjLength(ip, script, &sock->script_llength); + cancel(sock); + + if (newscript) { + rc= scriptinv_set(&sock->script, ip, newscript); if (rc) return rc; } - cancel(sock); - if (script) { - Tcl_IncrRefCount(script); - sock->script= script; - sock->ip= ip; - } Tcl_CreateFileHandler(sock->fd, TCL_READABLE, recv_call, sock); return TCL_OK; } diff --git a/hbytes/hbytes.h b/hbytes/hbytes.h index f7d0110..484f10d 100644 --- a/hbytes/hbytes.h +++ b/hbytes/hbytes.h @@ -175,6 +175,21 @@ int sockaddr_len(const SockAddr_Value*); const struct sockaddr *sockaddr_addr(const SockAddr_Value*); void sockaddr_free(const SockAddr_Value*); +/* from scriptinv.c */ + +typedef struct { /* semi-opaque - read only, and then only where commented */ + Tcl_Interp *ip; /* valid, non-0 and useable if set */ + Tcl_Obj *obj; /* non-0 iff set (but only test for 0/non-0) */ + int llength; +} ScriptToInvoke; + +void scriptinv_init(ScriptToInvoke *si); +int scriptinv_set(ScriptToInvoke *si, Tcl_Interp *ip, Tcl_Obj *newscript); +void scriptinv_cancel(ScriptToInvoke *si); /* then don't invoke */ + /* no separate free function - just cancel */ + +void scriptinv_invoke(ScriptToInvoke *si, int argc, Tcl_Obj **argv); + /* from idtable.c */ typedef struct { diff --git a/tuntap/tuntap.c b/tuntap/tuntap.c index a4d9f9a..5543302 100644 --- a/tuntap/tuntap.c +++ b/tuntap/tuntap.c @@ -1,12 +1,11 @@ /* */ /* - * tuntap-socket create-ptp [] - * => - * tuntap-socket close - * tuntap-socket ifname - * tuntap-socket receive - * tuntap-socket on-transmit [