4 * dgram-socket create <local> => <sockid>
5 * dgram-socket close <sockid>
6 * dgram-socket transmit <sockid> <data> <remote>
7 * dgram-socket on-receive <sockid> [<script>]
8 * calls, effectively, eval <script> [list <data> <remote-addr> <socket>]
9 * if script not supplied, cancel
15 typedef struct DgramSocket {
20 static DgramSocket *socks;
22 static int sockfail(Tcl_Interp *ip, int fd, const char *m) {
26 return posixerr(ip,e,m);
29 int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip,
30 SockAddr_Value local, int *sock_r) {
32 const struct sockaddr *sa;
34 for (sock=0; sock<n_socks && socks[sock].fd>=0; sock++);
38 socks= (void*)Tcl_Realloc((void*)socks, n_socks*sizeof(*socks));
39 while (sock<n_socks) socks[sock++].fd=-1;
43 sa= sockaddr_addr(&local);
44 al= sockaddr_len(&local);
46 fd= socket(sa->sa_family, SOCK_DGRAM, 0);
47 if (fd<0) return posixerr(ip,errno,"socket");
48 r= bind(fd, sa, al); if (r) return sockfail(ip,fd,"bind");
49 r= setnonblock(fd, 1); if (r) return sockfail(ip,fd,"setnonblock");
56 int do_dgram_socket_transmit(ClientData cd, Tcl_Interp *ip,
57 int sock, HBytes_Value data,
58 SockAddr_Value remote) {
61 r= sendto(socks[sock].fd,
62 hbytes_data(&data), l=hbytes_len(&data),
64 sockaddr_addr(&remote), sockaddr_len(&remote));
65 if (r==-1) return posixerr(ip,errno,"sendto");
66 else if (r!=l) return staticerr(ip,"sendto gave wrong answer");
70 int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, int sock) {
71 close(socks[sock].fd); /* nothing useful to be done with errors */
78 int pat_sockid(Tcl_Interp *ip, Tcl_Obj *o, int *val) {
81 rc= Tcl_ConvertToType(ip,o,&sockid_type);
84 sock= o->internalRep.longValue;
85 if (sock >= n_socks || socks[sock].fd==-1)
86 return staticerr(ip,"dgram socket not open");
92 Tcl_Obj *ret_sockid(Tcl_Interp *ip, int val) {
96 Tcl_InvalidateStringRep(o);
97 o->internalRep.longValue= val;
98 o->typePtr= &sockid_type;
102 static void sockid_t_free(Tcl_Obj *o) { }
104 static void sockid_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
105 dup->internalRep= src->internalRep;
108 static void sockid_t_ustr(Tcl_Obj *o) {
112 snprintf(buf,sizeof(buf),"dgramsock%d", (int)o->internalRep.longValue);
113 l= o->length= strlen(buf);
114 o->bytes= TALLOC(l+1);
115 strcpy(o->bytes, buf);
118 static int sockid_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
122 str= Tcl_GetStringFromObj(o,0);
123 if (memcmp(str,"dgramsock",9)) return staticerr(ip,"bad dgram socket id");
124 errno=0; ul=strtoul(str+9,&ep,10);
125 if (errno || *ep) return staticerr(ip,"bad dgram socket id number");
126 if (ul > INT_MAX) return staticerr(ip,"out of range dgram socket id");
127 o->internalRep.longValue= ul;
131 Tcl_ObjType sockid_type = {
133 sockid_t_free, sockid_t_dup, sockid_t_ustr, sockid_t_sfa