From 6e8398df98237d7cf85fc14e369534f7ffa833a9 Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Mon, 20 May 2013 22:37:36 +0000 Subject: Added a port method to change the listening port. svn path=/trunk/externals/mrpeach/; revision=17143 --- net/tcpserver-help.pd | 86 +++++++++++++++++++++++---------------------- net/tcpserver.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 141 insertions(+), 42 deletions(-) diff --git a/net/tcpserver-help.pd b/net/tcpserver-help.pd index 097b785..13defdc 100644 --- a/net/tcpserver-help.pd +++ b/net/tcpserver-help.pd @@ -1,20 +1,20 @@ -#N canvas 1 53 1284 779 12; +#N canvas 322 104 1272 779 12; #X msg 39 -10 print; -#X floatatom 344 316 5 0 0 0 - - -; -#X floatatom 368 366 5 0 0 0 - - -; -#X obj 392 317 unpack 0 0 0 0; -#X floatatom 392 340 3 0 0 0 - - -; -#X floatatom 423 340 3 0 0 0 - - -; -#X floatatom 455 340 3 0 0 0 - - -; -#X floatatom 489 340 3 0 0 0 - - -; -#X text 349 339 from; -#X text 260 316 connections; -#X obj 321 441 print received; +#X floatatom 404 376 5 0 0 0 - - -; +#X floatatom 428 426 5 0 0 0 - - -; +#X obj 452 377 unpack 0 0 0 0; +#X floatatom 452 400 3 0 0 0 - - -; +#X floatatom 483 400 3 0 0 0 - - -; +#X floatatom 515 400 3 0 0 0 - - -; +#X floatatom 549 400 3 0 0 0 - - -; +#X text 409 399 from; +#X text 320 376 connections; +#X obj 381 501 print received; #X msg 135 86 client 1 1 2 3; #X msg 63 14 broadcast 1 2 3; #X text 91 -9 list of connections; #X text 186 14 send to all clients; -#X text 298 366 on socket; +#X text 358 426 on socket; #X msg -11 -60 send 504 1 2 3; #X text 100 -65 send to client on socket 504; #X msg 647 -209 client 1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @@ -53,7 +53,7 @@ #X msg -41 -90 disconnectsocket \$1; #X msg -84 -133 disconnectclient \$1; #X obj 647 257 s toserver; -#X obj 321 264 r toserver; +#X obj 381 324 r toserver; #X floatatom 143 -172 5 0 0 0 - - -; #X obj 121 -153 f; #X obj 121 -172 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 @@ -63,12 +63,12 @@ #X obj 163 -129 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 -241291 -1; #X text -109 -110 disconnect by socket or client number; -#X text 428 291 argument is port number; -#X text -8 293 Received messages are output as lists of bytes; -#X text -69 397 ***WARNING*** Attempting to print long messages can +#X text 488 351 argument is port number; +#X text 52 353 Received messages are output as lists of bytes; +#X text -9 457 ***WARNING*** Attempting to print long messages can hang pd!; -#X obj 321 419 spigot; -#X obj 360 399 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 +#X obj 381 479 spigot; +#X obj 420 459 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 -45076 0 1; #X msg 159 110 dump \$1; #X obj -17 95 tgl 15 0 empty empty enable_dump 17 7 0 10 -4034 -257985 @@ -77,7 +77,7 @@ hang pd!; #X text -85 61 characters to main; #X text -85 76 window in hexdump; #X text -85 92 format:; -#X obj 321 292 tcpserver 9997; +#X obj 381 352 tcpserver 9997; #X msg -132 -181 client 1 test.txt; #X text 647 -234 [tcpserver] sends and receives bytes on [0...255] ; @@ -85,41 +85,40 @@ hang pd!; ; #X text -137 -202 send a file to client 1; #X msg 183 134 client 1 72 101 108 108 111 13 10; -#X floatatom 578 377 9 0 0 0 - - -; -#X obj 710 336 print status; -#X floatatom 538 400 5 0 0 0 - - -; -#X text 468 399 to_client; +#X floatatom 638 437 9 0 0 0 - - -; +#X obj 770 396 print status; +#X floatatom 598 460 5 0 0 0 - - -; +#X text 528 459 to_client; #X msg 111 62 client; #X msg 88 39 client 1; #X text 156 38 get state of client 1; #X text 249 86 send (binary) 1 2 3 to client 1; -#X floatatom 712 469 5 0 0 0 - - -; -#X symbolatom 744 442 20 0 0 0 - - -; -#X floatatom 681 442 5 0 0 0 - - -; -#X text 645 376 bytes; -#X text 538 376 sent; +#X floatatom 772 529 5 0 0 0 - - -; +#X symbolatom 804 502 20 0 0 0 - - -; +#X floatatom 741 502 5 0 0 0 - - -; +#X text 705 436 bytes; +#X text 598 436 sent; #X msg 209 160 clientbuf 1 65536; -#X obj 681 418 unpack 0 0 s 0; -#X floatatom 776 490 7 0 0 0 - - -; -#X text 621 490 length of send buffer:; -#X text 661 468 socket:; -#X text 630 441 client:; -#X text 721 441 ip:; +#X obj 741 478 unpack 0 0 s 0; +#X floatatom 836 550 7 0 0 0 - - -; +#X text 681 550 length of send buffer:; +#X text 721 528 socket:; +#X text 690 501 client:; +#X text 781 501 ip:; #X text 339 159 set send-buffer size for client 1; #X text 163 62 get state of all clients (list on right outlet); -#X obj 538 351 unpack 0 0 0; -#X floatatom 619 418 5 0 0 0 - - -; -#X text 549 417 on_socket; +#X obj 598 411 unpack 0 0 0; +#X floatatom 679 478 5 0 0 0 - - -; +#X text 609 477 on_socket; #X msg 233 184 send; #X msg 258 209 1156; #X text 276 183 output 'client' message for all sockets; #X text 298 209 output 'client' message for socket 1156; #X msg 283 234 unblock; -#X obj 538 312 route sent client blocked; +#X obj 598 372 route sent client blocked; #X text -143 233 If sending too many messages blocks the system \, tcpserver will stop sending until it receives an unblock message; -#X obj 652 359 print blocked; -#X text -69 476 2010/03/27 Martin Peach; +#X obj 712 419 print blocked; #N canvas 529 82 494 344 META 0; #X text 12 225 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; @@ -134,7 +133,11 @@ send print broadcast dump clientbuf unblock; #X text 12 145 OUTLET_2 float; #X text 12 165 OUTLET_3 list; #X text 12 185 OUTLET_4 sent client blocked; -#X restore 839 398 pd META; +#X restore 899 458 pd META; +#X msg 335 286 port 12345; +#X text 417 285 change listening port (only if no connections are active) +; +#X text -9 536 2013/05/20 Martin Peach; #X connect 0 0 60 0; #X connect 3 0 4 0; #X connect 3 1 5 0; @@ -197,3 +200,4 @@ send print broadcast dump clientbuf unblock; #X connect 96 1 80 0; #X connect 96 2 98 0; #X connect 96 3 67 0; +#X connect 100 0 60 0; 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); } -- cgit v1.2.1