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>]
14 typedef struct DgramSocket {
19 static DgramSocket *socks;
21 static int sockfail(Tcl_Interp *ip, int fd, const char *m) {
25 return posixerr(ip,e,m);
28 int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip,
29 SockAddr_Value local, int *sock_r) {
31 const struct sockaddr *sa;
33 for (sock=0; sock<n_socks && socks[sock].fd>=0; sock++);
37 socks= (void*)Tcl_Realloc((void*)socks, n_socks*sizeof(*socks));
38 while (sock<n_socks) socks[sock++].fd=-1;
42 sa= sockaddr_addr(&local);
43 al= sockaddr_len(&local);
45 fd= socket(sa->sa_family, SOCK_DGRAM, 0);
46 if (fd<0) return posixerr(ip,errno,"socket");
47 r= bind(fd, sa, al); if (r) return sockfail(ip,fd,"bind");
48 r= setnonblock(fd, 1); if (r) return sockfail(ip,fd,"setnonblock");
55 int do_dgram_socket_close(ClientData cd, Tcl_Interp *ip, int sock) {
56 close(socks[sock].fd); /* nothing useful to be done with errors */
63 int pat_sockid(Tcl_Interp *ip, Tcl_Obj *o, int *val) {
66 rc= Tcl_ConvertToType(ip,o,&sockid_type);
69 sock= o->internalRep.longValue;
70 if (sock >= n_socks || socks[sock].fd==-1)
71 return staticerr(ip,"dgram socket not open");
77 Tcl_Obj *ret_sockid(Tcl_Interp *ip, int val) {
81 Tcl_InvalidateStringRep(o);
82 o->internalRep.longValue= val;
83 o->typePtr= &sockid_type;
87 static void sockid_t_free(Tcl_Obj *o) { }
89 static void sockid_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
90 dup->internalRep= src->internalRep;
93 static void sockid_t_ustr(Tcl_Obj *o) {
97 snprintf(buf,sizeof(buf),"dgramsock%d", (int)o->internalRep.longValue);
98 l= o->length= strlen(buf);
99 o->bytes= TALLOC(l+1);
100 strcpy(o->bytes, buf);
103 static int sockid_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
107 str= Tcl_GetStringFromObj(o,0);
108 if (memcmp(str,"dgramsock",9)) return staticerr(ip,"bad dgram socket id");
109 errno=0; ul=strtoul(str+9,&ep,10);
110 if (errno || *ep) return staticerr(ip,"bad dgram socket id number");
111 if (ul > INT_MAX) return staticerr(ip,"out of range dgram socket id");
112 o->internalRep.longValue= ul;
116 Tcl_ObjType sockid_type = {
118 sockid_t_free, sockid_t_dup, sockid_t_ustr, sockid_t_sfa