X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=dgram%2Fdgram.c;h=ff16917fb352c3843f2ea911ba79185223c8fcd7;hp=81487921b7cbca3900d7d66f6734bb9ed671b71d;hb=9b2c18cc9d122b45f9e737864921d32baa599f0c;hpb=b6017ccf067a7fefa893c8bf19288a1909f17263 diff --git a/dgram/dgram.c b/dgram/dgram.c index 8148792..ff16917 100644 --- a/dgram/dgram.c +++ b/dgram/dgram.c @@ -14,15 +14,13 @@ 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; -IdDataTable dgram_socks= { "dgramsock" }; - int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip, SockAddr_Value local, void **sock_r) { int fd, al, r; @@ -40,11 +38,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 +64,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 +99,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,53 +125,49 @@ 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; } -int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, void *sock_v) { - DgramSocket *sock= sock_v; - int sockix; +static void destroy(DgramSocket *sock) { cancel(sock); close(sock->fd); /* nothing useful to be done with errors */ - sockix= sock->ix; TFREE(sock->addr_buf); TFREE(sock->msg_buf); TFREE(sock); - dgram_socks.a[sockix]= 0; +} + +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 +};