summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/x_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/x_net.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/x_net.c726
1 files changed, 726 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/x_net.c b/apps/plugins/pdbox/PDa/src/x_net.c
new file mode 100644
index 0000000000..5094661214
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/x_net.c
@@ -0,0 +1,726 @@
1/* Copyright (c) 1997-1999 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* network */
6
7#include "m_pd.h"
8#include "s_stuff.h"
9
10#include <sys/types.h>
11#include <string.h>
12#ifdef UNIX
13#include <sys/socket.h>
14#include <netinet/in.h>
15#include <netinet/tcp.h>
16#include <netdb.h>
17#include <stdio.h>
18#define SOCKET_ERROR -1
19#else
20#include <winsock.h>
21#endif
22
23static t_class *netsend_class;
24
25typedef struct _netsend
26{
27 t_object x_obj;
28 int x_fd;
29 int x_protocol;
30} t_netsend;
31
32static void *netsend_new(t_floatarg udpflag)
33{
34 t_netsend *x = (t_netsend *)pd_new(netsend_class);
35 outlet_new(&x->x_obj, &s_float);
36 x->x_fd = -1;
37 x->x_protocol = (udpflag != 0 ? SOCK_DGRAM : SOCK_STREAM);
38 return (x);
39}
40
41static void netsend_connect(t_netsend *x, t_symbol *hostname,
42 t_floatarg fportno)
43{
44 struct sockaddr_in server;
45 struct hostent *hp;
46 int sockfd;
47 int portno = fportno;
48 int intarg;
49 if (x->x_fd >= 0)
50 {
51 error("netsend_connect: already connected");
52 return;
53 }
54
55 /* create a socket */
56 sockfd = socket(AF_INET, x->x_protocol, 0);
57#if 0
58 fprintf(stderr, "send socket %d\n", sockfd);
59#endif
60 if (sockfd < 0)
61 {
62 sys_sockerror("socket");
63 return;
64 }
65 /* connect socket using hostname provided in command line */
66 server.sin_family = AF_INET;
67 hp = gethostbyname(hostname->s_name);
68 if (hp == 0)
69 {
70 post("bad host?\n");
71 return;
72 }
73#if 0
74 intarg = 0;
75 if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
76 &intarg, sizeof(intarg)) < 0)
77 post("setsockopt (SO_RCVBUF) failed\n");
78#endif
79 /* for stream (TCP) sockets, specify "nodelay" */
80 if (x->x_protocol == SOCK_STREAM)
81 {
82 intarg = 1;
83 if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
84 &intarg, sizeof(intarg)) < 0)
85 post("setsockopt (TCP_NODELAY) failed\n");
86 }
87 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
88
89 /* assign client port number */
90 server.sin_port = htons((u_short)portno);
91
92 post("connecting to port %d", portno);
93 /* try to connect. LATER make a separate thread to do this
94 because it might block */
95 if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
96 {
97 sys_sockerror("connecting stream socket");
98 sys_closesocket(sockfd);
99 return;
100 }
101 x->x_fd = sockfd;
102 outlet_float(x->x_obj.ob_outlet, 1);
103}
104
105static void netsend_disconnect(t_netsend *x)
106{
107 if (x->x_fd >= 0)
108 {
109 sys_closesocket(x->x_fd);
110 x->x_fd = -1;
111 outlet_float(x->x_obj.ob_outlet, 0);
112 }
113}
114
115static void netsend_send(t_netsend *x, t_symbol *s, int argc, t_atom *argv)
116{
117 if (x->x_fd >= 0)
118 {
119 t_binbuf *b = binbuf_new();
120 char *buf, *bp;
121 int length, sent;
122 t_atom at;
123 binbuf_add(b, argc, argv);
124 SETSEMI(&at);
125 binbuf_add(b, 1, &at);
126 binbuf_gettext(b, &buf, &length);
127 for (bp = buf, sent = 0; sent < length;)
128 {
129 static double lastwarntime;
130 static double pleasewarn;
131 double timebefore = sys_getrealtime();
132 int res = send(x->x_fd, buf, length-sent, 0);
133 double timeafter = sys_getrealtime();
134 int late = (timeafter - timebefore > 0.005);
135 if (late || pleasewarn)
136 {
137 if (timeafter > lastwarntime + 2)
138 {
139 post("netsend blocked %d msec",
140 (int)(1000 * ((timeafter - timebefore) + pleasewarn)));
141 pleasewarn = 0;
142 lastwarntime = timeafter;
143 }
144 else if (late) pleasewarn += timeafter - timebefore;
145 }
146 if (res <= 0)
147 {
148 sys_sockerror("netsend");
149 netsend_disconnect(x);
150 break;
151 }
152 else
153 {
154 sent += res;
155 bp += res;
156 }
157 }
158 t_freebytes(buf, length);
159 binbuf_free(b);
160 }
161 else error("netsend: not connected");
162}
163
164static void netsend_free(t_netsend *x)
165{
166 netsend_disconnect(x);
167}
168
169static void netsend_setup(void)
170{
171 netsend_class = class_new(gensym("netsend"), (t_newmethod)netsend_new,
172 (t_method)netsend_free,
173 sizeof(t_netsend), 0, A_DEFFLOAT, 0);
174 class_addmethod(netsend_class, (t_method)netsend_connect,
175 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
176 class_addmethod(netsend_class, (t_method)netsend_disconnect,
177 gensym("disconnect"), 0);
178 class_addmethod(netsend_class, (t_method)netsend_send, gensym("send"),
179 A_GIMME, 0);
180}
181
182/* ----------------------------- netreceive ------------------------- */
183
184static t_class *netreceive_class;
185
186typedef struct _netreceive
187{
188 t_object x_obj;
189 t_outlet *x_msgout;
190 t_outlet *x_connectout;
191 int x_connectsocket;
192 int x_nconnections;
193 int x_udp;
194} t_netreceive;
195
196static void netreceive_notify(t_netreceive *x)
197{
198 outlet_float(x->x_connectout, --x->x_nconnections);
199}
200
201static void netreceive_doit(void *z, t_binbuf *b)
202{
203 t_atom messbuf[1024];
204 t_netreceive *x = (t_netreceive *)z;
205 int msg, natom = binbuf_getnatom(b);
206 t_atom *at = binbuf_getvec(b);
207 for (msg = 0; msg < natom;)
208 {
209 int emsg;
210 for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
211 && at[emsg].a_type != A_SEMI; emsg++)
212 ;
213 if (emsg > msg)
214 {
215 int i;
216 for (i = msg; i < emsg; i++)
217 if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
218 {
219 pd_error(x, "netreceive: got dollar sign in message");
220 goto nodice;
221 }
222 if (at[msg].a_type == A_FLOAT)
223 {
224 if (emsg > msg + 1)
225 outlet_list(x->x_msgout, 0, emsg-msg, at + msg);
226 else outlet_float(x->x_msgout, at[msg].a_w.w_float);
227 }
228 else if (at[msg].a_type == A_SYMBOL)
229 outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
230 emsg-msg-1, at + msg + 1);
231 }
232 nodice:
233 msg = emsg + 1;
234 }
235}
236
237static void netreceive_connectpoll(t_netreceive *x)
238{
239 int fd = accept(x->x_connectsocket, 0, 0);
240 if (fd < 0) post("netreceive: accept failed");
241 else
242 {
243 t_socketreceiver *y = socketreceiver_new((void *)x,
244 (t_socketnotifier)netreceive_notify,
245 (x->x_msgout ? netreceive_doit : 0), 0);
246 sys_addpollfn(fd, (t_fdpollfn)socketreceiver_read, y);
247 outlet_float(x->x_connectout, ++x->x_nconnections);
248 }
249}
250
251static void *netreceive_new(t_symbol *compatflag,
252 t_floatarg fportno, t_floatarg udpflag)
253{
254 t_netreceive *x;
255 struct sockaddr_in server;
256 int sockfd, portno = fportno, udp = (udpflag != 0);
257 int old = !strcmp(compatflag->s_name , "old");
258 int intarg;
259 /* create a socket */
260 sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0);
261#if 0
262 fprintf(stderr, "receive socket %d\n", sockfd);
263#endif
264 if (sockfd < 0)
265 {
266 sys_sockerror("socket");
267 return (0);
268 }
269 server.sin_family = AF_INET;
270 server.sin_addr.s_addr = INADDR_ANY;
271
272#if 1
273 /* ask OS to allow another Pd to repoen this port after we close it. */
274 intarg = 1;
275 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
276 &intarg, sizeof(intarg)) < 0)
277 post("setsockopt (SO_REUSEADDR) failed\n");
278#endif
279#if 0
280 intarg = 0;
281 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
282 &intarg, sizeof(intarg)) < 0)
283 post("setsockopt (SO_RCVBUF) failed\n");
284#endif
285 /* Stream (TCP) sockets are set NODELAY */
286 if (!udp)
287 {
288 intarg = 1;
289 if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
290 &intarg, sizeof(intarg)) < 0)
291 post("setsockopt (TCP_NODELAY) failed\n");
292 }
293 /* assign server port number */
294 server.sin_port = htons((u_short)portno);
295
296 /* name the socket */
297 if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
298 {
299 sys_sockerror("bind");
300 sys_closesocket(sockfd);
301 return (0);
302 }
303 x = (t_netreceive *)pd_new(netreceive_class);
304 if (old)
305 {
306 /* old style, nonsecure version */
307 x->x_msgout = 0;
308 }
309 else x->x_msgout = outlet_new(&x->x_obj, &s_anything);
310
311 if (udp) /* datagram protocol */
312 {
313 t_socketreceiver *y = socketreceiver_new((void *)x,
314 (t_socketnotifier)netreceive_notify,
315 (x->x_msgout ? netreceive_doit : 0), 1);
316 sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y);
317 x->x_connectout = 0;
318 }
319 else /* streaming protocol */
320 {
321 if (listen(sockfd, 5) < 0)
322 {
323 sys_sockerror("listen");
324 sys_closesocket(sockfd);
325 sockfd = -1;
326 }
327 else
328 {
329 sys_addpollfn(sockfd, (t_fdpollfn)netreceive_connectpoll, x);
330 x->x_connectout = outlet_new(&x->x_obj, &s_float);
331 }
332 }
333 x->x_connectsocket = sockfd;
334 x->x_nconnections = 0;
335 x->x_udp = udp;
336
337 return (x);
338}
339
340static void netreceive_free(t_netreceive *x)
341{
342 /* LATER make me clean up open connections */
343 if (x->x_connectsocket >= 0)
344 {
345 sys_rmpollfn(x->x_connectsocket);
346 sys_closesocket(x->x_connectsocket);
347 }
348}
349
350static void netreceive_setup(void)
351{
352 netreceive_class = class_new(gensym("netreceive"),
353 (t_newmethod)netreceive_new, (t_method)netreceive_free,
354 sizeof(t_netreceive), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT,
355 A_DEFSYM, 0);
356}
357
358void x_net_setup(void)
359{
360 netsend_setup();
361 netreceive_setup();
362}
363
364/* Copyright (c) 1997-1999 Miller Puckette.
365* For information on usage and redistribution, and for a DISCLAIMER OF ALL
366* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
367
368/* network */
369
370#include "m_pd.h"
371#include "s_stuff.h"
372
373#include <sys/types.h>
374#include <string.h>
375#ifdef UNIX
376#include <sys/socket.h>
377#include <netinet/in.h>
378#include <netinet/tcp.h>
379#include <netdb.h>
380#include <stdio.h>
381#define SOCKET_ERROR -1
382#else
383#include <winsock.h>
384#endif
385
386static t_class *netsend_class;
387
388typedef struct _netsend
389{
390 t_object x_obj;
391 int x_fd;
392 int x_protocol;
393} t_netsend;
394
395static void *netsend_new(t_floatarg udpflag)
396{
397 t_netsend *x = (t_netsend *)pd_new(netsend_class);
398 outlet_new(&x->x_obj, &s_float);
399 x->x_fd = -1;
400 x->x_protocol = (udpflag != 0 ? SOCK_DGRAM : SOCK_STREAM);
401 return (x);
402}
403
404static void netsend_connect(t_netsend *x, t_symbol *hostname,
405 t_floatarg fportno)
406{
407 struct sockaddr_in server;
408 struct hostent *hp;
409 int sockfd;
410 int portno = fportno;
411 int intarg;
412 if (x->x_fd >= 0)
413 {
414 error("netsend_connect: already connected");
415 return;
416 }
417
418 /* create a socket */
419 sockfd = socket(AF_INET, x->x_protocol, 0);
420#if 0
421 fprintf(stderr, "send socket %d\n", sockfd);
422#endif
423 if (sockfd < 0)
424 {
425 sys_sockerror("socket");
426 return;
427 }
428 /* connect socket using hostname provided in command line */
429 server.sin_family = AF_INET;
430 hp = gethostbyname(hostname->s_name);
431 if (hp == 0)
432 {
433 post("bad host?\n");
434 return;
435 }
436#if 0
437 intarg = 0;
438 if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
439 &intarg, sizeof(intarg)) < 0)
440 post("setsockopt (SO_RCVBUF) failed\n");
441#endif
442 /* for stream (TCP) sockets, specify "nodelay" */
443 if (x->x_protocol == SOCK_STREAM)
444 {
445 intarg = 1;
446 if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
447 &intarg, sizeof(intarg)) < 0)
448 post("setsockopt (TCP_NODELAY) failed\n");
449 }
450 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
451
452 /* assign client port number */
453 server.sin_port = htons((u_short)portno);
454
455 post("connecting to port %d", portno);
456 /* try to connect. LATER make a separate thread to do this
457 because it might block */
458 if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
459 {
460 sys_sockerror("connecting stream socket");
461 sys_closesocket(sockfd);
462 return;
463 }
464 x->x_fd = sockfd;
465 outlet_float(x->x_obj.ob_outlet, 1);
466}
467
468static void netsend_disconnect(t_netsend *x)
469{
470 if (x->x_fd >= 0)
471 {
472 sys_closesocket(x->x_fd);
473 x->x_fd = -1;
474 outlet_float(x->x_obj.ob_outlet, 0);
475 }
476}
477
478static void netsend_send(t_netsend *x, t_symbol *s, int argc, t_atom *argv)
479{
480 if (x->x_fd >= 0)
481 {
482 t_binbuf *b = binbuf_new();
483 char *buf, *bp;
484 int length, sent;
485 t_atom at;
486 binbuf_add(b, argc, argv);
487 SETSEMI(&at);
488 binbuf_add(b, 1, &at);
489 binbuf_gettext(b, &buf, &length);
490 for (bp = buf, sent = 0; sent < length;)
491 {
492 static double lastwarntime;
493 static double pleasewarn;
494 double timebefore = sys_getrealtime();
495 int res = send(x->x_fd, buf, length-sent, 0);
496 double timeafter = sys_getrealtime();
497 int late = (timeafter - timebefore > 0.005);
498 if (late || pleasewarn)
499 {
500 if (timeafter > lastwarntime + 2)
501 {
502 post("netsend blocked %d msec",
503 (int)(1000 * ((timeafter - timebefore) + pleasewarn)));
504 pleasewarn = 0;
505 lastwarntime = timeafter;
506 }
507 else if (late) pleasewarn += timeafter - timebefore;
508 }
509 if (res <= 0)
510 {
511 sys_sockerror("netsend");
512 netsend_disconnect(x);
513 break;
514 }
515 else
516 {
517 sent += res;
518 bp += res;
519 }
520 }
521 t_freebytes(buf, length);
522 binbuf_free(b);
523 }
524 else error("netsend: not connected");
525}
526
527static void netsend_free(t_netsend *x)
528{
529 netsend_disconnect(x);
530}
531
532static void netsend_setup(void)
533{
534 netsend_class = class_new(gensym("netsend"), (t_newmethod)netsend_new,
535 (t_method)netsend_free,
536 sizeof(t_netsend), 0, A_DEFFLOAT, 0);
537 class_addmethod(netsend_class, (t_method)netsend_connect,
538 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
539 class_addmethod(netsend_class, (t_method)netsend_disconnect,
540 gensym("disconnect"), 0);
541 class_addmethod(netsend_class, (t_method)netsend_send, gensym("send"),
542 A_GIMME, 0);
543}
544
545/* ----------------------------- netreceive ------------------------- */
546
547static t_class *netreceive_class;
548
549typedef struct _netreceive
550{
551 t_object x_obj;
552 t_outlet *x_msgout;
553 t_outlet *x_connectout;
554 int x_connectsocket;
555 int x_nconnections;
556 int x_udp;
557} t_netreceive;
558
559static void netreceive_notify(t_netreceive *x)
560{
561 outlet_float(x->x_connectout, --x->x_nconnections);
562}
563
564static void netreceive_doit(void *z, t_binbuf *b)
565{
566 t_atom messbuf[1024];
567 t_netreceive *x = (t_netreceive *)z;
568 int msg, natom = binbuf_getnatom(b);
569 t_atom *at = binbuf_getvec(b);
570 for (msg = 0; msg < natom;)
571 {
572 int emsg;
573 for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
574 && at[emsg].a_type != A_SEMI; emsg++)
575 ;
576 if (emsg > msg)
577 {
578 int i;
579 for (i = msg; i < emsg; i++)
580 if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
581 {
582 pd_error(x, "netreceive: got dollar sign in message");
583 goto nodice;
584 }
585 if (at[msg].a_type == A_FLOAT)
586 {
587 if (emsg > msg + 1)
588 outlet_list(x->x_msgout, 0, emsg-msg, at + msg);
589 else outlet_float(x->x_msgout, at[msg].a_w.w_float);
590 }
591 else if (at[msg].a_type == A_SYMBOL)
592 outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
593 emsg-msg-1, at + msg + 1);
594 }
595 nodice:
596 msg = emsg + 1;
597 }
598}
599
600static void netreceive_connectpoll(t_netreceive *x)
601{
602 int fd = accept(x->x_connectsocket, 0, 0);
603 if (fd < 0) post("netreceive: accept failed");
604 else
605 {
606 t_socketreceiver *y = socketreceiver_new((void *)x,
607 (t_socketnotifier)netreceive_notify,
608 (x->x_msgout ? netreceive_doit : 0), 0);
609 sys_addpollfn(fd, (t_fdpollfn)socketreceiver_read, y);
610 outlet_float(x->x_connectout, ++x->x_nconnections);
611 }
612}
613
614static void *netreceive_new(t_symbol *compatflag,
615 t_floatarg fportno, t_floatarg udpflag)
616{
617 t_netreceive *x;
618 struct sockaddr_in server;
619 int sockfd, portno = fportno, udp = (udpflag != 0);
620 int old = !strcmp(compatflag->s_name , "old");
621 int intarg;
622 /* create a socket */
623 sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0);
624#if 0
625 fprintf(stderr, "receive socket %d\n", sockfd);
626#endif
627 if (sockfd < 0)
628 {
629 sys_sockerror("socket");
630 return (0);
631 }
632 server.sin_family = AF_INET;
633 server.sin_addr.s_addr = INADDR_ANY;
634
635#if 1
636 /* ask OS to allow another Pd to repoen this port after we close it. */
637 intarg = 1;
638 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
639 &intarg, sizeof(intarg)) < 0)
640 post("setsockopt (SO_REUSEADDR) failed\n");
641#endif
642#if 0
643 intarg = 0;
644 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
645 &intarg, sizeof(intarg)) < 0)
646 post("setsockopt (SO_RCVBUF) failed\n");
647#endif
648 /* Stream (TCP) sockets are set NODELAY */
649 if (!udp)
650 {
651 intarg = 1;
652 if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
653 &intarg, sizeof(intarg)) < 0)
654 post("setsockopt (TCP_NODELAY) failed\n");
655 }
656 /* assign server port number */
657 server.sin_port = htons((u_short)portno);
658
659 /* name the socket */
660 if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
661 {
662 sys_sockerror("bind");
663 sys_closesocket(sockfd);
664 return (0);
665 }
666 x = (t_netreceive *)pd_new(netreceive_class);
667 if (old)
668 {
669 /* old style, nonsecure version */
670 x->x_msgout = 0;
671 }
672 else x->x_msgout = outlet_new(&x->x_obj, &s_anything);
673
674 if (udp) /* datagram protocol */
675 {
676 t_socketreceiver *y = socketreceiver_new((void *)x,
677 (t_socketnotifier)netreceive_notify,
678 (x->x_msgout ? netreceive_doit : 0), 1);
679 sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y);
680 x->x_connectout = 0;
681 }
682 else /* streaming protocol */
683 {
684 if (listen(sockfd, 5) < 0)
685 {
686 sys_sockerror("listen");
687 sys_closesocket(sockfd);
688 sockfd = -1;
689 }
690 else
691 {
692 sys_addpollfn(sockfd, (t_fdpollfn)netreceive_connectpoll, x);
693 x->x_connectout = outlet_new(&x->x_obj, &s_float);
694 }
695 }
696 x->x_connectsocket = sockfd;
697 x->x_nconnections = 0;
698 x->x_udp = udp;
699
700 return (x);
701}
702
703static void netreceive_free(t_netreceive *x)
704{
705 /* LATER make me clean up open connections */
706 if (x->x_connectsocket >= 0)
707 {
708 sys_rmpollfn(x->x_connectsocket);
709 sys_closesocket(x->x_connectsocket);
710 }
711}
712
713static void netreceive_setup(void)
714{
715 netreceive_class = class_new(gensym("netreceive"),
716 (t_newmethod)netreceive_new, (t_method)netreceive_free,
717 sizeof(t_netreceive), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT,
718 A_DEFSYM, 0);
719}
720
721void x_net_setup(void)
722{
723 netsend_setup();
724 netreceive_setup();
725}
726