aboutsummaryrefslogtreecommitdiff
path: root/net/tcpserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tcpserver.c')
-rw-r--r--net/tcpserver.c97
1 files changed, 96 insertions, 1 deletions
diff --git a/net/tcpserver.c b/net/tcpserver.c
index 379a7ec..ca872b4 100644
--- a/net/tcpserver.c
+++ b/net/tcpserver.c
@@ -112,6 +112,7 @@ typedef struct _tcpserver
t_atom x_addrbytes[4];
t_int x_sock_fd;
t_int x_connectsocket;
+ t_int x_port;
t_int x_nconnections;
t_int x_blocked;
t_atom x_msgoutbuf[MAX_UDP_RECEIVE];
@@ -151,6 +152,7 @@ static void tcpserver_connectpoll(t_tcpserver *x);
static void tcpserver_print(t_tcpserver *x);
static void tcpserver_unblock(t_tcpserver *x);
static void *tcpserver_new(t_floatarg fportno);
+static void tcpserver_port(t_tcpserver *x, t_floatarg fportno);
static void tcpserver_free(t_tcpserver *x);
void tcpserver_setup(void);
static void tcpserver_dump(t_tcpserver *x, t_float dump);
@@ -1142,6 +1144,96 @@ static void tcpserver_unblock(t_tcpserver *x)
x->x_blocked = 0;
}
+static void tcpserver_port(t_tcpserver*x, t_floatarg fportno)
+{
+ t_atom output_atom;
+ int portno = fportno;
+ struct sockaddr_in server;
+ socklen_t serversize = sizeof(server);
+ int sockfd = x->x_connectsocket;
+ int optVal = 1;
+ int optLen = sizeof(int);
+
+
+ if(x->x_port == portno) return;
+
+ if(x->x_nconnections > 0)
+ {
+ post ("%s: can't change port (connection count is %d)", objName, x->x_nconnections);
+ return;
+ }
+
+ SETFLOAT(&output_atom, -1);
+
+ /* shut down the old socket */
+ if (sockfd >= 0)
+ {
+ sys_rmpollfn(sockfd);
+ sys_closesocket(sockfd);
+ x->x_connectsocket = -1;
+ x->x_port = -1;
+ }
+
+ /* create a whole new socket */
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+#ifdef DEBUG
+ post("%s: receive socket %d", objName, sockfd);
+#endif
+ if (sockfd < 0)
+ {
+ sys_sockerror("tcpserver: socket");
+ return;
+ }
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
+ /* enable reuse of local address */
+#ifdef _WIN32
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&optVal, optLen) == SOCKET_ERROR)
+#else
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&optVal, optLen) == -1)
+#endif
+ sys_sockerror("tcpserver: setsockopt SO_REUSEADDR");
+
+ /* assign server port number */
+ server.sin_port = htons((u_short)portno);
+ /* name the socket */
+ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0)
+ {
+ sys_sockerror("tcpserver: bind");
+ sys_closesocket(sockfd);
+ outlet_anything(x->x_status_outlet, gensym("port"), 1, &output_atom);
+ return;
+ }
+
+ /* streaming protocol */
+ if (listen(sockfd, 5) < 0)
+ {
+ sys_sockerror("tcpserver: listen");
+ sys_closesocket(sockfd);
+ sockfd = -1;
+ outlet_anything(x->x_status_outlet, gensym("port"), 1, &output_atom);
+ return;
+ }
+ else
+ {
+ sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll, x); // wait for new connections
+ }
+
+ x->x_connectsocket = sockfd;
+ x->x_nconnections = 0;
+ x->x_blocked = 0;
+
+
+ // 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);
+ }
+
+ SETFLOAT(&output_atom, x->x_port);
+ outlet_anything(x->x_status_outlet, gensym("port"), 1, &output_atom);
+}
+
static void *tcpserver_new(t_floatarg fportno)
{
t_tcpserver *x;
@@ -1215,10 +1307,12 @@ static void *tcpserver_new(t_floatarg fportno)
x->x_addrbytes[i].a_type = A_FLOAT;
x->x_addrbytes[i].a_w.w_float = 0;
}
- post ("tcpserver listening on port %d", portno);
+ x->x_port = portno;
+ post ("tcpserver listening on port %d", x->x_port);
return (x);
}
+
static void tcpserver_free(t_tcpserver *x)
{
int i;
@@ -1257,6 +1351,7 @@ void tcpserver_setup(void)
class_addmethod(tcpserver_class, (t_method)tcpserver_dump, gensym("dump"), A_FLOAT, 0);
class_addmethod(tcpserver_class, (t_method)tcpserver_unblock, gensym("unblock"), 0);
class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast, gensym("broadcast"), A_GIMME, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_port, gensym("port"), A_FLOAT, 0);
class_addlist(tcpserver_class, (t_method)tcpserver_send);
}