static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; struct hostent *hp; int sockfd; int portno = fportno; int intarg; memset(&server, 0, sizeof(server)); if (x->x_fd >= 0) { iemnet_log(x, IEMNET_ERROR, "already connected"); return; } /* resolve hostname provided as argument */ server.sin_family = AF_INET; hp = gethostbyname(hostname->s_name); if (hp == 0) { iemnet_log(x, IEMNET_ERROR, "bad host '%s'?", hostname->s_name); return; } /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { iemnet_log(x, IEMNET_ERROR, "unable to open socket"); sys_sockerror("socket"); return; } /* for stream (TCP) sockets, specify "nodelay" */ intarg = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to enable immediate sending"); sys_sockerror("setsockopt"); } /* connect socket using hostname provided as argument */ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); iemnet_log(x, IEMNET_VERBOSE, "connecting to port %d", portno); /* try to connect. */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to initiate connection on socket %d", sockfd); sys_sockerror("connect"); iemnet__closesocket(sockfd, 1); return; } x->x_fd = sockfd; x->x_sender=iemnet__sender_create(sockfd, NULL, NULL, 0); outlet_float(x->x_obj.ob_outlet, 1); }
static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; struct hostent *hp; int sockfd; int portno = fportno; int intarg; memset(&server, 0, sizeof(server)); if (x->x_fd >= 0) { error("tcpsend: already connected"); return; } /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { sys_sockerror("tcpsend: socket"); return; } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(hostname->s_name); if (hp == 0) { post("tcpsend: bad host?\n"); return; } /* for stream (TCP) sockets, specify "nodelay" */ intarg = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) post("tcpsend: setsockopt (TCP_NODELAY) failed\n"); memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); post("tcpsend: connecting to port %d", portno); /* try to connect. */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("tcpsend: connecting stream socket"); sys_closesocket(sockfd); return; } x->x_fd = sockfd; x->x_sender=iemnet__sender_create(sockfd, 0); outlet_float(x->x_obj.ob_outlet, 1); }
static void *tcpclient_child_connect(void *w) { t_tcpclient *x = (t_tcpclient*) w; struct sockaddr_in server; struct hostent *hp; int sockfd; if (x->x_fd >= 0) { error("%s_child_connect: already connected", objName); return (x); } /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); #ifdef DEBUG post("%s: send socket %d\n", objName, sockfd); #endif if (sockfd < 0) { sys_sockerror("tcpclient: socket"); return (x); } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(x->x_hostname); if (hp == 0) { sys_sockerror("tcpclient: bad host?\n"); return (x); } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)x->x_port); if (x->x_verbosity) post("%s: connecting socket %d to port %d", objName, sockfd, x->x_port); /* try to connect */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("tcpclient: connecting stream socket"); sys_closesocket(sockfd); return (x); } x->x_fd = sockfd; x->x_addr = ntohl(*(long *)hp->h_addr); /* outlet_float is not threadsafe ! */ // outlet_float(x->x_obj.ob_outlet, 1); x->x_connectstate = 1; x->x_blocked = 0; /* use callback instead to set outlet */ clock_delay(x->x_clock, 0); return (x); }
static void streamout13_connect(t_streamout13 *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; struct hostent *hp; int sockfd; int portno = fportno; x->hostname = hostname; x->portno = (int) fportno; if (x->x_fd >= 0) { error("streamout13_connect: already connected - reconnecting"); sys_closesocket(x->x_fd); x->x_fd = -1; outlet_float(x->x_obj.ob_outlet, 0); } /* create a socket */ sockfd = socket(AF_INET, x->x_protocol, 0); if (sockfd < 0) { post("streamout13: Connection to %s on port %d failed",hostname->s_name,portno); sys_sockerror("socket"); return; } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(hostname->s_name); if (hp == 0) { post("bad host?\n"); return; } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); /* try to connect. LATER make a separate thread to do this because it might block */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("connecting stream socket"); sys_closesocket(sockfd); return; } post("connected host %s on port %d",hostname->s_name, portno); x->x_fd = sockfd; outlet_float(x->x_obj.ob_outlet, 1); }
static void *netdist_child_connect(void *w) { int i; t_netdist *x = (t_netdist*) w; struct sockaddr_in server; struct hostent *hp; int sockfd; int portno; i = x->x_numconnect + 1; portno = x->x_port[i]; /* create a socket */ sockfd = socket(AF_INET, x->x_protocol, 0); #if 0 fprintf(stderr, "send socket %d\n", sockfd); #endif if (sockfd < 0) { sys_sockerror("socket"); return (x); } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(x->x_hostname[i]); if (hp == 0) { post("bad host?\n"); return (x); } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); post("connecting to port %d", portno); /* try to connect */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("connecting stream socket"); sys_closesocket(sockfd); return (x); } x->x_fd[i] = sockfd; /* outlet_float is not threadsafe ! */ // outlet_float(x->x_obj.ob_outlet, 1); x->x_numconnect++; /* count connection */ /* use callback instead to set outlet */ clock_delay(x->x_clock, 0); return (x); }
static void netsend_readbin(t_netsend *x, int fd) { unsigned char inbuf[MAXPDSTRING]; int ret = recv(fd, inbuf, MAXPDSTRING, 0), i; if (!x->x_msgout) { bug("netsend_readbin"); return; } if (ret <= 0) { if (ret < 0) sys_sockerror("recv"); sys_rmpollfn(fd); sys_closesocket(fd); if (x->x_obj.ob_pd == netreceive_class) netreceive_notify((t_netreceive *)x, fd); } else if (x->x_protocol == SOCK_DGRAM) { t_atom *ap = (t_atom *)alloca(ret * sizeof(t_atom)); for (i = 0; i < ret; i++) SETFLOAT(ap+i, inbuf[i]); outlet_list(x->x_msgout, 0, ret, ap); } else { for (i = 0; i < ret; i++) outlet_float(x->x_msgout, inbuf[i]); } }
static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) { int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); int ret, i; t_tcpserver *y = x->sr_owner; y->x_sock_fd = fd; /* the input buffer might be full. If so, drop the whole thing */ if (readto == x->sr_inhead) { post("%s: dropped message", objName); x->sr_inhead = x->sr_intail = 0; readto = INBUFSIZE; } else { ret = recv(fd, x->sr_inbuf + x->sr_inhead, readto - x->sr_inhead, 0); if (ret < 0) { sys_sockerror("tcpserver: recv"); if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); sys_rmpollfn(fd); sys_closesocket(fd); } else if (ret == 0) { post("%s: connection closed on socket %d", objName, fd); if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); sys_rmpollfn(fd); sys_closesocket(fd); } else { #ifdef DEBUG post ("%s_socketreceiver_read: ret = %d", objName, ret); #endif x->sr_inhead += ret; if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; /* output client's IP and socket no. */ for(i = 0; i < y->x_nconnections; i++) /* search for corresponding IP */ { if(y->x_sr[i]->sr_fd == y->x_sock_fd) { // outlet_symbol(x->x_connectionip, x->x_sr[i].sr_host); /* find sender's ip address and output it */ y->x_addrbytes[0].a_w.w_float = (y->x_sr[i]->sr_addr & 0xFF000000)>>24; y->x_addrbytes[1].a_w.w_float = (y->x_sr[i]->sr_addr & 0x0FF0000)>>16; y->x_addrbytes[2].a_w.w_float = (y->x_sr[i]->sr_addr & 0x0FF00)>>8; y->x_addrbytes[3].a_w.w_float = (y->x_sr[i]->sr_addr & 0x0FF); outlet_list(y->x_addrout, &s_list, 4L, y->x_addrbytes); break; } } outlet_float(y->x_sockout, y->x_sock_fd); /* the socket number */ tcpserver_socketreceiver_doread(x); } }
static void netrec_socketreceiver_read(t_netrec_socketreceiver *x, int fd) { if (x->sr_udp) /* UDP ("datagram") socket protocol */ netrec_socketreceiver_getudp(x, fd); else /* TCP ("streaming") socket protocol */ { char *semi; int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); int ret; t_netrec *y = x->sr_owner; y->x_sock_fd = fd; /* the input buffer might be full. If so, drop the whole thing */ if (readto == x->sr_inhead) { fprintf(stderr, "netrec: dropped message"); x->sr_inhead = x->sr_intail = 0; readto = INBUFSIZE; } else { ret = recv(fd, x->sr_inbuf + x->sr_inhead, readto - x->sr_inhead, 0); if (ret < 0) { sys_sockerror("recv"); if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); sys_rmpollfn(fd); sys_closesocket(fd); } else if (ret == 0) { post("netrec: connection closed on socket %d", fd); if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); sys_rmpollfn(fd); sys_closesocket(fd); } else { x->sr_inhead += ret; if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; while (netrec_socketreceiver_doread(x)) { outlet_setstacklim(); if (x->sr_socketreceivefn) (*x->sr_socketreceivefn)(x->sr_owner, inbinbuf); else binbuf_eval(inbinbuf, 0, 0, 0); } } } } }
static void netsend_send(t_netsend *x, t_symbol *s, int argc, t_atom *argv) { #ifdef ROCKBOX (void) x; (void) s; (void) argc; (void) argv; #else /* ROCKBOX */ if (x->x_fd >= 0) { t_binbuf *b = binbuf_new(); char *buf, *bp; int length, sent; t_atom at; binbuf_add(b, argc, argv); SETSEMI(&at); binbuf_add(b, 1, &at); binbuf_gettext(b, &buf, &length); for (bp = buf, sent = 0; sent < length;) { static double lastwarntime; static double pleasewarn; double timebefore = sys_getrealtime(); int res = send(x->x_fd, buf, length-sent, 0); double timeafter = sys_getrealtime(); int late = (timeafter - timebefore > 0.005); if (late || pleasewarn) { if (timeafter > lastwarntime + 2) { post("netsend blocked %d msec", (int)(1000 * ((timeafter - timebefore) + pleasewarn))); pleasewarn = 0; lastwarntime = timeafter; } else if (late) pleasewarn += timeafter - timebefore; } if (res <= 0) { sys_sockerror("netsend"); netsend_disconnect(x); break; } else { sent += res; bp += res; } } t_freebytes(buf, length); binbuf_free(b); } else error("netsend: not connected"); #endif /* ROCKBOX */ }
static void netdist_send(t_netdist *x, t_symbol *s, int argc, t_atom *argv) { int i = 0; for(i = 0; i <= x->x_numconnect; i++) { if (x->x_fd[i] >= 0) { t_binbuf *b = binbuf_new(); char *buf, *bp; int length, sent; t_atom at; binbuf_add(b, argc, argv); SETSEMI(&at); binbuf_add(b, 1, &at); binbuf_gettext(b, &buf, &length); for (bp = buf, sent = 0; sent < length;) { static double lastwarntime; static double pleasewarn; double timebefore = clock_getlogicaltime(); int res = send(x->x_fd[i], buf, length-sent, 0); double timeafter = clock_getlogicaltime(); int late = (timeafter - timebefore > 0.005); if (late || pleasewarn) { if (timeafter > lastwarntime + 2) { post("netdist blocked %d msec", (int)(1000 * ((timeafter - timebefore) + pleasewarn))); pleasewarn = 0; lastwarntime = timeafter; } else if (late) pleasewarn += timeafter - timebefore; } if (res <= 0) { sys_sockerror("netdist"); netdist_disconnect(x, gensym(x->x_hostname[i]), x->x_port[i]); break; } else { sent += res; bp += res; } } t_freebytes(buf, length); binbuf_free(b); } } if(x->x_numconnect == -1) error("netdist: not connected"); }
static void netserver_socketreceiver_read(t_netserver_socketreceiver *x, int fd) { char *semi; int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); int ret; t_netserver *y = x->sr_owner; y->x_sock_fd = fd; /* the input buffer might be full. If so, drop the whole thing */ if (readto == x->sr_inhead) { if (y->x_log_pri >= LOG_ERR) post("netserver: dropped message"); x->sr_inhead = x->sr_intail = 0; readto = INBUFSIZE; } else { ret = recv(fd, x->sr_inbuf + x->sr_inhead, readto - x->sr_inhead, 0); if (ret < 0) { sys_sockerror("recv"); if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); sys_rmpollfn(fd); sys_closesocket(fd); } else if (ret == 0) { if (y->x_log_pri >= LOG_NOTICE) post("netserver: << connection closed on socket %d", fd); if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); sys_rmpollfn(fd); sys_closesocket(fd); } else { x->sr_inhead += ret; if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; while (netserver_socketreceiver_doread(x)) { outlet_setstacklim(); if (x->sr_socketreceivefn) (*x->sr_socketreceivefn)(x->sr_owner, inbinbuf); else binbuf_eval(inbinbuf, 0, 0, 0); } } } }
static void netrec_socketreceiver_getudp(t_netrec_socketreceiver *x, int fd) { char buf[INBUFSIZE+1]; int ret = recv(fd, buf, INBUFSIZE, 0); if (ret < 0) { sys_sockerror("recv"); sys_rmpollfn(fd); sys_closesocket(fd); } else if (ret > 0) { buf[ret] = 0; #if 0 post("%s", buf); #endif if (buf[ret-1] != '\n') { #if 0 buf[ret] = 0; error("dropped bad buffer %s\n", buf); #endif } else { char *semi = strchr(buf, ';'); if (semi) *semi = 0; binbuf_text(inbinbuf, buf, strlen(buf)); outlet_setstacklim(); if (x->sr_socketreceivefn) (*x->sr_socketreceivefn)(x->sr_owner, inbinbuf); else bug("netrec_socketreceiver_getudp"); } } }
static void tcpclient_sent(t_tcpclient *x) { t_atom output_atom; if (x->x_sendresult < 0) { sys_sockerror("tcpclient: send"); post("%s_sent: could not send data ", objName); x->x_blocked++; SETFLOAT(&output_atom, x->x_sendresult); outlet_anything( x->x_statusout, gensym("blocked"), 1, &output_atom); } else if (x->x_sendresult == 0) { /* assume the message is queued and will be sent real soon now */ SETFLOAT(&output_atom, x->x_sendbuf_len); outlet_anything( x->x_statusout, gensym("sent"), 1, &output_atom); x->x_sendbuf_len = 0; /* we might be called only once for multiple calls to tcpclient_send_buf */ } else { SETFLOAT(&output_atom, x->x_sendresult); outlet_anything( x->x_statusout, gensym("sent"), 1, &output_atom); } }
static void udpreceive_port(t_udpreceive*x, t_floatarg fportno) { static t_atom ap[1]; int portno = fportno; struct sockaddr_in server; socklen_t serversize=sizeof(server); int sockfd = x->x_connectsocket; int intarg; SETFLOAT(ap, -1); if(x->x_port == portno) { return; } /* cleanup any open ports */ if(sockfd>=0) { iemnet__receiver_destroy(x->x_receiver); x->x_connectsocket=-1; x->x_port=-1; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd<0) { error("[%s]: unable to create socket", objName); return; } /* ask OS to allow another Pd to reopen this port after we close it. */ #ifdef SO_REUSEADDR intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&intarg, sizeof(intarg)) < 0) { error("[%s]: setsockopt (SO_REUSEADDR) failed", objName); } #endif /* SO_REUSEADDR */ #ifdef SO_REUSEPORT intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (char *)&intarg, sizeof(intarg)) < 0) { error("[%s]: setsockopt (SO_REUSEPORT) failed", objName); } #endif /* SO_REUSEPORT */ server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { sys_sockerror("[udpreceive] bind failed"); sys_closesocket(sockfd); sockfd = -1; outlet_anything(x->x_statout, gensym("port"), 1, ap); return; } x->x_connectsocket = sockfd; x->x_port = portno; // find out which port is actually used (useful when assigning "0") if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); } x->x_receiver=iemnet__receiver_create(sockfd, x, udpreceive_read_callback); SETFLOAT(ap, x->x_port); outlet_anything(x->x_statout, gensym("port"), 1, ap); }
static void *udpclient_child_connect(void *w) { t_udpclient *x = (t_udpclient*) w; struct sockaddr_in server; struct hostent *hp; int sockfd; int broadcast = 1;/* nonzero is true */ if (x->x_sender) { error("[%s] already connected", objName); return (x); } /* create a socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { sys_sockerror("udpclient: socket"); return (x); } /* Based on zmoelnig's patch 2221504: Enable sending of broadcast messages (if hostname is a broadcast address)*/ #ifdef SO_BROADCAST if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&broadcast, sizeof(broadcast))) { error("[%s] couldn't switch to broadcast mode", objName); } #endif /* SO_BROADCAST */ /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(x->x_hostname); if (hp == 0) { error("[%s] bad host '%s'?", objName, x->x_hostname); return (x); } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)x->x_port); DEBUG("connecting to port %d", x->x_port); /* try to connect. */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("udpclient: connecting stream socket"); sys_closesocket(sockfd); return (x); } x->x_fd = sockfd; x->x_addr = ntohl(*(long *)hp->h_addr); x->x_sender=iemnet__sender_create(sockfd); x->x_receiver=iemnet__receiver_create(sockfd, x, udpclient_receive_callback); x->x_connectstate = 1; clock_delay(x->x_clock, 0); return (x); }
static int udpreceive_setport(t_udpreceive*x, unsigned short portno) { struct sockaddr_in server; socklen_t serversize=sizeof(server); int sockfd = x->x_connectsocket; int intarg; memset(&server, 0, sizeof(server)); if(x->x_port == portno) { return 1; } /* cleanup any open ports */ if(sockfd>=0) { iemnet__receiver_destroy(x->x_receiver, 0); x->x_connectsocket=-1; x->x_port=-1; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd<0) { pd_error(x, "[%s]: unable to create socket", objName); return 0; } /* ask OS to allow another Pd to reopen this port after we close it. */ #ifdef SO_REUSEADDR if(x->x_reuseaddr) { intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&intarg, sizeof(intarg)) < 0) { pd_error(x, "[%s]: setsockopt (SO_REUSEADDR) failed", objName); } } #endif /* SO_REUSEADDR */ #ifdef SO_REUSEPORT if(x->x_reuseport) { intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&intarg, sizeof(intarg)) < 0) { pd_error(x, "[%s]: setsockopt (SO_REUSEPORT) failed", objName); } } #endif /* SO_REUSEPORT */ server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { sys_sockerror("[udpreceive] bind failed"); sys_closesocket(sockfd); sockfd = -1; return 0; } x->x_connectsocket = sockfd; x->x_port = portno; // find out which port is actually used (useful when assigning "0") if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); } x->x_receiver=iemnet__receiver_create(sockfd, x, udpreceive_read_callback, 0); return 1; }
static void *tcpclient_child_connect(void *w) { t_tcpclient *x = (t_tcpclient*) w; struct sockaddr_in server; struct hostent *hp; int sockfd; t_iemnet_sender*sender; t_iemnet_receiver*receiver; if (x->x_fd >= 0) { error("%s_connect: already connected", objName); return (x); } /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { sys_sockerror("tcpclient: socket"); return (x); } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(x->x_hostname); if (hp == 0) { sys_sockerror("tcpclient: bad host?\n"); return (x); } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)x->x_port); /* try to connect */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("tcpclient: connecting stream socket"); sys_closesocket(sockfd); return (x); } sender=iemnet__sender_create(sockfd); receiver=iemnet__receiver_create(sockfd, x, tcpclient_receive_callback); /* update the tcpclient-object (thread safe) */ sys_lock(); x->x_fd = sockfd; x->x_addr = ntohl(*(long *)hp->h_addr); x->x_sender=sender; x->x_receiver=receiver; x->x_connectstate = 1; /* use callback to set outlet in main thread */ clock_delay(x->x_clock, 0); sys_unlock(); return (x); }
static void netreceive_listen(t_netreceive *x, t_floatarg fportno) { int portno = fportno, intarg; struct sockaddr_in server; netreceive_closeall(x); if (portno <= 0) return; x->x_ns.x_sockfd = socket(AF_INET, x->x_ns.x_protocol, 0); if (x->x_ns.x_sockfd < 0) { sys_sockerror("socket"); return; } #if 0 fprintf(stderr, "receive socket %d\n", x->x_ sockfd); #endif #if 1 /* ask OS to allow another Pd to repoen this port after we close it. */ intarg = 1; if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&intarg, sizeof(intarg)) < 0) post("netreceive: setsockopt (SO_REUSEADDR) failed\n"); #endif #if 0 intarg = 0; if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_RCVBUF, &intarg, sizeof(intarg)) < 0) post("setsockopt (SO_RCVBUF) failed\n"); #endif intarg = 1; if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&intarg, sizeof(intarg)) < 0) post("netreceive: failed to sett SO_BROADCAST"); /* Stream (TCP) sockets are set NODELAY */ if (x->x_ns.x_protocol == SOCK_STREAM) { intarg = 1; if (setsockopt(x->x_ns.x_sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) post("setsockopt (TCP_NODELAY) failed\n"); } /* assign server port number etc */ server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(x->x_ns.x_sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { sys_sockerror("bind"); sys_closesocket(x->x_ns.x_sockfd); x->x_ns.x_sockfd = -1; return; } if (x->x_ns.x_protocol == SOCK_DGRAM) /* datagram protocol */ { if (x->x_ns.x_bin) sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)netsend_readbin, x); else { t_socketreceiver *y = socketreceiver_new((void *)x, (t_socketnotifier)netreceive_notify, (x->x_ns.x_msgout ? netsend_doit : 0), 1); sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)socketreceiver_read, y); x->x_ns.x_connectout = 0; } } else /* streaming protocol */ { if (listen(x->x_ns.x_sockfd, 5) < 0) { sys_sockerror("listen"); sys_closesocket(x->x_ns.x_sockfd); x->x_ns.x_sockfd = -1; } else { sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)netreceive_connectpoll, x); x->x_ns.x_connectout = outlet_new(&x->x_ns.x_obj, &s_float); } } }
static int netsend_dosend(t_netsend *x, int sockfd, t_symbol *s, int argc, t_atom *argv) { char *buf, *bp; int length, sent, fail = 0; t_binbuf *b = 0; if (x->x_bin) { int i; buf = alloca(argc); for (i = 0; i < argc; i++) ((unsigned char *)buf)[i] = atom_getfloatarg(i, argc, argv); length = argc; } else { t_atom at; b = binbuf_new(); binbuf_add(b, argc, argv); SETSEMI(&at); binbuf_add(b, 1, &at); binbuf_gettext(b, &buf, &length); } for (bp = buf, sent = 0; sent < length;) { static double lastwarntime; static double pleasewarn; double timebefore = sys_getrealtime(); int res = send(sockfd, bp, length-sent, 0); double timeafter = sys_getrealtime(); int late = (timeafter - timebefore > 0.005); if (late || pleasewarn) { if (timeafter > lastwarntime + 2) { post("netsend/netreceive blocked %d msec", (int)(1000 * ((timeafter - timebefore) + pleasewarn))); pleasewarn = 0; lastwarntime = timeafter; } else if (late) pleasewarn += timeafter - timebefore; } if (res <= 0) { sys_sockerror("netsend"); fail = 1; break; } else { sent += res; bp += res; } } done: if (!x->x_bin) { t_freebytes(buf, length); binbuf_free(b); } return (fail); }
static void netsend_connect(t_netsend *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; struct hostent *hp; int sockfd; int portno = fportno; int intarg; if (x->x_sockfd >= 0) { error("netsend_connect: already connected"); return; } /* create a socket */ sockfd = socket(AF_INET, x->x_protocol, 0); #if 0 fprintf(stderr, "send socket %d\n", sockfd); #endif if (sockfd < 0) { sys_sockerror("socket"); return; } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(hostname->s_name); if (hp == 0) { post("bad host?\n"); return; } #if 0 intarg = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &intarg, sizeof(intarg)) < 0) post("setsockopt (SO_RCVBUF) failed\n"); #endif intarg = 1; if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&intarg, sizeof(intarg)) < 0) post("setting SO_BROADCAST"); /* for stream (TCP) sockets, specify "nodelay" */ if (x->x_protocol == SOCK_STREAM) { intarg = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) post("setsockopt (TCP_NODELAY) failed\n"); } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); post("connecting to port %d", portno); /* try to connect. LATER make a separate thread to do this because it might block */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("connecting stream socket"); sys_closesocket(sockfd); return; } x->x_sockfd = sockfd; if (x->x_bin) sys_addpollfn(sockfd, (t_fdpollfn)netsend_readbin, x); else { t_socketreceiver *y = socketreceiver_new((void *)x, 0, netsend_doit, 0); sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y); } outlet_float(x->x_obj.ob_outlet, 1); }
static void *netreceive_new(t_symbol *compatflag, t_floatarg fportno, t_floatarg udpflag) { t_netreceive *x; struct sockaddr_in server; int sockfd, portno = fportno, udp = (udpflag != 0); int old = !strcmp(compatflag->s_name , "old"); int intarg; /* create a socket */ sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0); #if 0 fprintf(stderr, "receive socket %d\n", sockfd); #endif if (sockfd < 0) { sys_sockerror("socket"); return (0); } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; #if 1 /* ask OS to allow another Pd to repoen this port after we close it. */ intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&intarg, sizeof(intarg)) < 0) post("setsockopt (SO_REUSEADDR) failed\n"); #endif #if 0 intarg = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &intarg, sizeof(intarg)) < 0) post("setsockopt (SO_RCVBUF) failed\n"); #endif intarg = 1; if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&intarg, sizeof(intarg)) < 0) post("setting SO_BROADCAST"); /* Stream (TCP) sockets are set NODELAY */ if (!udp) { intarg = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) post("setsockopt (TCP_NODELAY) failed\n"); } /* assign server port number */ server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { sys_sockerror("bind"); sys_closesocket(sockfd); return (0); } x = (t_netreceive *)pd_new(netreceive_class); if (old) { /* old style, nonsecure version */ x->x_msgout = 0; } else x->x_msgout = outlet_new(&x->x_obj, &s_anything); if (udp) /* datagram protocol */ { t_socketreceiver *y = socketreceiver_new((void *)x, (t_socketnotifier)netreceive_notify, (x->x_msgout ? netreceive_doit : 0), 1); sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y); x->x_connectout = 0; } else /* streaming protocol */ { if (listen(sockfd, 5) < 0) { sys_sockerror("listen"); sys_closesocket(sockfd); sockfd = -1; } else { sys_addpollfn(sockfd, (t_fdpollfn)netreceive_connectpoll, x); x->x_connectout = outlet_new(&x->x_obj, &s_float); } } x->x_connectsocket = sockfd; x->x_nconnections = 0; x->x_udp = udp; return (x); }
static void *netrec_new(t_symbol *compatflag, t_floatarg fportno, t_floatarg udpflag) { t_netrec *x; int i; struct sockaddr_in server; int sockfd, portno = fportno, udp = (udpflag != 0); int old = !strcmp(compatflag->s_name , "old"); /* create a socket */ sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0); #if 1 post("netrec: receive socket %d\n", sockfd); #endif if (sockfd < 0) { sys_sockerror("socket"); return (0); } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; #ifdef IRIX /* this seems to work only in IRIX but is unnecessary in Linux. Not sure what NT needs in place of this. */ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) post("setsockopt failed\n"); #endif /* assign server port number */ server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { sys_sockerror("bind"); sys_closesocket(sockfd); return (0); } x = (t_netrec *)pd_new(netrec_class); if (old) { /* old style, nonsecure version */ x->x_msgout = 0; } else x->x_msgout = outlet_new(&x->x_obj, &s_anything); if (udp) /* datagram protocol */ { t_netrec_socketreceiver *y = netrec_socketreceiver_new((void *)x, (t_netrec_socketnotifier)netrec_notify, (x->x_msgout ? netrec_doit : 0), 1); sys_addpollfn(sockfd, (t_fdpollfn)netrec_socketreceiver_read, y); x->x_connectout = 0; } else /* streaming protocol */ { if (listen(sockfd, 5) < 0) { sys_sockerror("listen"); sys_closesocket(sockfd); sockfd = -1; } else { sys_addpollfn(sockfd, (t_fdpollfn)netrec_connectpoll, x); x->x_connectout = outlet_new(&x->x_obj, &s_float); x->x_clientno = outlet_new(&x->x_obj, &s_float); x->x_connectionip = outlet_new(&x->x_obj, &s_symbol); inbinbuf = binbuf_new(); } } x->x_connectsocket = sockfd; x->x_nconnections = 0; x->x_udp = udp; for(i = 0; i < MAX_CONNECT; i++)x->x_fd[i] = -1; return (x); }
/* send message to client using client number note that the client numbers might change in case a client disconnects! */ static void netserver_client_send(t_netserver *x, t_symbol *s, int argc, t_atom *argv) { int sockfd, client; if(x->x_nconnections < 0) { if (x->x_log_pri >= LOG_WARNING) post("netserver: no clients connected"); return; } if(argc < 2) { if (x->x_log_pri >= LOG_WARNING) post("netserver: nothing to send"); return; } /* get number of client (first element in list) */ if(argv[0].a_type == A_FLOAT) client = atom_getfloatarg(0, argc, argv); else { if (x->x_log_pri >= LOG_WARNING) post("netserver: no client specified"); return; } sockfd = x->x_fd[client - 1]; /* get socket number for that client */ /* process & send data */ if(sockfd > 0) { t_binbuf *b = binbuf_new(); char *buf, *bp; int length, sent; t_atom at; binbuf_add(b, argc - 1, argv + 1); /* skip first element */ SETSEMI(&at); binbuf_add(b, 1, &at); binbuf_gettext(b, &buf, &length); if (x->x_log_pri >= LOG_DEBUG) { post("netserver: sending data to client %d on socket %d", client, sockfd); post("netserver: >> sending \"%s\"", buf); } for (bp = buf, sent = 0; sent < length;) { static double lastwarntime; static double pleasewarn; double timebefore = clock_getlogicaltime(); int res = send(sockfd, buf, length-sent, 0); double timeafter = clock_getlogicaltime(); int late = (timeafter - timebefore > 0.005); if (late || pleasewarn) { if (timeafter > lastwarntime + 2) { if (x->x_log_pri >= LOG_WARNING) post("netserver blocked %d msec", (int)(1000 * ((timeafter - timebefore) + pleasewarn))); pleasewarn = 0; lastwarntime = timeafter; } else if (late) pleasewarn += timeafter - timebefore; } if (res <= 0) { sys_sockerror("netserver"); if (x->x_log_pri >= LOG_ERR) post("netserver: could not send data to cient"); break; } else { sent += res; bp += res; } } t_freebytes(buf, length); binbuf_free(b); } else if (x->x_log_pri >= LOG_CRIT) post("netserver: not a valid socket number (%d)", sockfd); }
static void udpsend_connect(t_udpsend *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; int sockfd; int portno = fportno; int broadcast = 1;/* nonzero is true */ if (x->x_sender) { error("[%s] already connected", objName); return; } /* create a socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { sys_sockerror("[udpsend] socket"); return; } /* Based on zmoelnig's patch 2221504: Enable sending of broadcast messages (if hostname is a broadcast address)*/ #ifdef SO_BROADCAST if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&broadcast, sizeof(broadcast))) { error("[%s] couldn't switch to broadcast mode", objName); } #endif /* SO_BROADCAST */ /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; do { #if 0 struct addrinfo * addr=NULL; if(getaddrinfo(hostname->s_name, NULL, NULL, &addr)) { error("[%s] bad host '%s'?", objName, hostname->s_name); return; } else { struct addrinfo * res; for (res = addr; res != NULL; res = res->ai_next) { struct sockaddr_in *sa = (struct sockaddr_in *) res->ai_addr; int len = res->ai_addrlen; // memcpy((char *)&server.sin_addr, (char *)res->ai_addr, hp->h_length); // LATER check how to do that... } } freeaddrinfo(addr); #else struct hostent *hp = gethostbyname(hostname->s_name); if (hp == 0) { error("[%s] bad host '%s'?", objName, hostname->s_name); return; } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); #endif } while(0); /* assign client port number */ server.sin_port = htons((u_short)portno); DEBUG("connecting to port %d", portno); /* try to connect. */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("[udpsend] connecting stream socket"); sys_closesocket(sockfd); return; } x->x_sender=iemnet__sender_create(sockfd, 0); outlet_float(x->x_obj.ob_outlet, 1); }
static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) { #define BYTE_BUF_LEN 65536 // arbitrary maximum similar to max IP packet size static char byte_buf[BYTE_BUF_LEN]; int i, j, d; unsigned char c; float f, e; char *bp; int length, sent; int result; static double lastwarntime; static double pleasewarn; double timebefore; double timeafter; int late; char fpath[FILENAME_MAX]; FILE *fptr; #ifdef DEBUG post("s: %s", s->s_name); post("argc: %d", argc); #endif for (i = j = 0; i < argc; ++i) { if (argv[i].a_type == A_FLOAT) { f = argv[i].a_w.w_float; d = (int)f; e = f - d; #ifdef DEBUG post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); #endif if (e != 0) { error("%s_send: item %d (%f) is not an integer", objName, i, f); return; } if ((d < 0) || (d > 255)) { error("%s: item %d (%f) is not between 0 and 255", objName, i, f); return; } c = (unsigned char)d; #ifdef DEBUG post("%s_send: argv[%d]: %d", objName, i, c); #endif byte_buf[j++] = c; } else if (argv[i].a_type == A_SYMBOL) { atom_string(&argv[i], fpath, FILENAME_MAX); #ifdef DEBUG post ("%s_send fname: %s", objName, fpath); #endif fptr = fopen(fpath, "rb"); if (fptr == NULL) { post("%s_send: unable to open \"%s\"", objName, fpath); return; } rewind(fptr); #ifdef DEBUG post("%s_send: d is %d", objName, d); #endif while ((d = fgetc(fptr)) != EOF) { byte_buf[j++] = (char)(d & 0x0FF); #ifdef DEBUG post("%s_send: byte_buf[%d] = %d", objName, j-1, byte_buf[j-1]); #endif if (j >= BYTE_BUF_LEN) { post ("%s_send: file too long, truncating at %lu", objName, BYTE_BUF_LEN); break; } } fclose(fptr); fptr = NULL; post("%s_send: read \"%s\" length %d byte%s", objName, fpath, j, ((d==1)?"":"s")); } else { error("%s_send: item %d is not a float or a file name", objName, i); return; } } length = j; if ((x->x_fd >= 0) && (length > 0)) { for (bp = byte_buf, sent = 0; sent < length;) { timebefore = sys_getrealtime(); result = send(x->x_fd, byte_buf, length-sent, 0); timeafter = sys_getrealtime(); late = (timeafter - timebefore > 0.005); if (late || pleasewarn) { if (timeafter > lastwarntime + 2) { post("%s_send blocked %d msec", objName, (int)(1000 * ((timeafter - timebefore) + pleasewarn))); pleasewarn = 0; lastwarntime = timeafter; } else if (late) pleasewarn += timeafter - timebefore; } if (result <= 0) { sys_sockerror("tcpclient_send"); tcpclient_disconnect(x); break; } else { sent += result; bp += result; } } } else error("%s: not connected", objName); }
static void *netserver_new(t_floatarg fportno) { t_netserver *x; int i; struct sockaddr_in server; int sockfd, portno = fportno; x = (t_netserver *)pd_new(netserver_class); /* set default debug message level */ x->x_log_pri = LOG_ERR; /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (x->x_log_pri >= LOG_NOTICE) post("netserver: receive socket %d", sockfd); if (sockfd < 0) { sys_sockerror("socket"); return (0); } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; #ifdef IRIX /* this seems to work only in IRIX but is unnecessary in Linux. Not sure what NT needs in place of this. */ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) post("setsockopt failed\n"); #endif /* assign server port number */ server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { sys_sockerror("bind"); sys_closesocket(sockfd); return (0); } x->x_msgout = outlet_new(&x->x_obj, &s_anything); /* streaming protocol */ if (listen(sockfd, 5) < 0) { sys_sockerror("listen"); sys_closesocket(sockfd); sockfd = -1; } else { sys_addpollfn(sockfd, (t_fdpollfn)netserver_connectpoll, x); x->x_connectout = outlet_new(&x->x_obj, &s_float); x->x_clientno = outlet_new(&x->x_obj, &s_float); x->x_connectionip = outlet_new(&x->x_obj, &s_symbol); inbinbuf = binbuf_new(); } x->x_connectsocket = sockfd; x->x_nconnections = 0; for(i = 0; i < MAX_CONNECT; i++)x->x_fd[i] = -1; return (x); }
static t_int *streamout13_perform(t_int *w) { t_streamout13* x = (t_streamout13*) (w[1]); int n = (int)(w[2]); int i,j,res = 0; int offset = 3; int sent = 0; int length ; char* buf = (char *)(w[2]); short* cibuf; char* bp; #ifndef _WIN32 t_float *in[x->x_n]; #else t_float** in = (t_float**) malloc(x->x_n * sizeof(t_float*)); #endif for (i=0;i < x->x_n;i++) { in[i] = (t_float *)(w[offset+i]); } if (x->x_fd > 0){ if (n != x->nsamples) streamout13_tempbuf(x,n); /* format the buffer */ /* cibuf = x->cbuf + x->blockssincesend * n * x->x_n + 2; while (n--){ for (j=0;j<x->x_n;j++){ *cibuf++ = (short) 32767.0 * *(in[j]++); } } */ switch (x->x_format) { case SF_FLOAT:{ t_float* fbuf = (t_float*) x->cbuf + x->blockssincesend * n * x->x_n + 1; while (n--){ for (j=0;j<x->x_n;j++){ *fbuf++ = *(in[j]++); } } break; } case SF_16BIT: { short* sbuf =(short*) x->cbuf + x->blockssincesend * n * x->x_n + 2; /*2 extra bytes for format & grain */ while (n--){ for (j=0;j<x->x_n;j++){ *sbuf++ = (short) 32767.0 * *(in[j]++); } } break; } case SF_8BIT: { // signed char* cbuf = (signed char*) ibuf; signed char* cbuf = (signed char*) x->cbuf + x->blockssincesend * n * x->x_n + 4; while (n--) for (j=0;j<x->x_n;j++){ *cbuf++ = (127.0 * *in[j]++); } } break; default: break; } if (!(x->blockssincesend < x->blockspersend - 1)){ x->blockssincesend=0; if (x->x_realformat !=x->x_format){ x->x_realformat = x->x_format; x->blockspersend = (int) (x->blockspersend * 4 / SF_SIZEOF(x->x_format)) ; x->nsamples=0; // post ("formatchange:%d",x->x_format); } if (x->blockspersend != (int) (x->newblockspersend * 4 / SF_SIZEOF(x->x_realformat)) ){ x->blockspersend = (int) (x->newblockspersend * 4 / SF_SIZEOF(x->x_realformat) ) ; x->nsamples=0; // post ("grainchange:%d",x->blockspersend); } cibuf=x->cbuf; *cibuf=(short)x->x_realformat; // *x->cbuf=(short)x->x_realformat; cibuf=x->cbuf + 1; *cibuf=x->blockspersend; // post ("out:cibuf:%d",*cibuf); /* send the buffer */ length = x->nsamples * x->x_n * x->blockspersend * SF_SIZEOF(x->x_realformat) + 4; // outlet_float(x->x_out2,length); // post ("out - length:%d",length); for (bp = buf, sent = 0; sent < length;) { res = send(x->x_fd, (char*) x->cbuf, length - sent , 0); if (res <= 0) { sys_sockerror("streamout13~-error"); streamout13_disconnect(x); break; } else { sent += res; bp += res; } } }else{ x->blockssincesend++; } } // post ("b-s-s:%d, length:%d, last:%d, prev:%d",x->blockssincesend,length,*cibuf,prev); #ifdef _WIN32 free(in); #endif return (w + 2 + i * 2); }