summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/u_pdreceive.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/u_pdreceive.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/u_pdreceive.c650
1 files changed, 650 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/u_pdreceive.c b/apps/plugins/pdbox/PDa/src/u_pdreceive.c
new file mode 100644
index 0000000000..3ec097edcc
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/u_pdreceive.c
@@ -0,0 +1,650 @@
1/* Copyright (c) 2000 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in the Pd distribution. */
4
5/* the "pdreceive" command. This is a standalone program that receives messages
6from Pd via the netsend/netreceive ("FUDI") protocol, and copies them to
7standard output. */
8
9#include <sys/types.h>
10#include <string.h>
11#include <stdio.h>
12#include <errno.h>
13#include <stdlib.h>
14#ifdef UNIX
15#include <sys/time.h>
16#include <unistd.h>
17#include <sys/socket.h>
18#include <netinet/in.h>
19#include <netdb.h>
20#define SOCKET_ERROR -1
21#else
22#include <winsock.h>
23#endif
24
25typedef struct _fdpoll
26{
27 int fdp_fd;
28 char *fdp_inbuf;
29 int fdp_inhead;
30 int fdp_intail;
31 int fdp_udp;
32} t_fdpoll;
33
34static int nfdpoll;
35static t_fdpoll *fdpoll;
36static int maxfd;
37static int sockfd;
38static int protocol;
39
40static void sockerror(char *s);
41static void x_closesocket(int fd);
42static void dopoll(void);
43#define BUFSIZE 4096
44
45int main(int argc, char **argv)
46{
47 int portno;
48 struct sockaddr_in server;
49 int nretry = 10;
50#ifdef MSW
51 short version = MAKEWORD(2, 0);
52 WSADATA nobby;
53#endif
54 if (argc < 2 || sscanf(argv[1], "%d", &portno) < 1 || portno <= 0)
55 goto usage;
56 if (argc >= 3)
57 {
58 if (!strcmp(argv[2], "tcp"))
59 protocol = SOCK_STREAM;
60 else if (!strcmp(argv[2], "udp"))
61 protocol = SOCK_DGRAM;
62 else goto usage;
63 }
64 else protocol = SOCK_STREAM;
65#ifdef MSW
66 if (WSAStartup(version, &nobby)) sockerror("WSAstartup");
67#endif
68 sockfd = socket(AF_INET, protocol, 0);
69 if (sockfd < 0)
70 {
71 sockerror("socket()");
72 exit(1);
73 }
74 maxfd = sockfd + 1;
75 server.sin_family = AF_INET;
76 server.sin_addr.s_addr = INADDR_ANY;
77
78#ifdef IRIX
79 /* this seems to work only in IRIX but is unnecessary in
80 Linux. Not sure what MSW needs in place of this. */
81 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0)
82 post("setsockopt failed\n");
83#endif
84
85 /* assign client port number */
86 server.sin_port = htons((unsigned short)portno);
87
88 /* name the socket */
89 if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
90 {
91 sockerror("bind");
92 x_closesocket(sockfd);
93 return (0);
94 }
95 if (protocol == SOCK_STREAM)
96 {
97 if (listen(sockfd, 5) < 0)
98 {
99 sockerror("listen");
100 x_closesocket(sockfd);
101 exit(1);
102 }
103 }
104 /* now loop forever selecting on sockets */
105 while (1)
106 dopoll();
107
108usage:
109 fprintf(stderr, "usage: pdreceive <portnumber> [udp|tcp]\n");
110 fprintf(stderr, "(default is tcp)\n");
111 exit(1);
112}
113
114static void addport(int fd)
115{
116 int nfd = nfdpoll;
117 t_fdpoll *fp;
118 fdpoll = (t_fdpoll *)realloc(fdpoll,
119 (nfdpoll+1) * sizeof(t_fdpoll));
120 fp = fdpoll + nfdpoll;
121 fp->fdp_fd = fd;
122 nfdpoll++;
123 if (fd >= maxfd) maxfd = fd + 1;
124 fp->fdp_inhead = fp->fdp_intail = 0;
125 if (!(fp->fdp_inbuf = malloc(BUFSIZE)))
126 {
127 fprintf(stderr, "out of memory");
128 exit(1);
129 }
130 printf("number_connected %d;\n", nfdpoll);
131}
132
133static void rmport(t_fdpoll *x)
134{
135 int nfd = nfdpoll;
136 int i, size = nfdpoll * sizeof(t_fdpoll);
137 t_fdpoll *fp;
138 for (i = nfdpoll, fp = fdpoll; i--; fp++)
139 {
140 if (fp == x)
141 {
142 x_closesocket(fp->fdp_fd);
143 free(fp->fdp_inbuf);
144 while (i--)
145 {
146 fp[0] = fp[1];
147 fp++;
148 }
149 fdpoll = (t_fdpoll *)realloc(fdpoll,
150 (nfdpoll-1) * sizeof(t_fdpoll));
151 nfdpoll--;
152 printf("number_connected %d;\n", nfdpoll);
153 return;
154 }
155 }
156 fprintf(stderr, "warning: item removed from poll list but not found");
157}
158
159static void doconnect(void)
160{
161 int fd = accept(sockfd, 0, 0);
162 if (fd < 0)
163 perror("accept");
164 else addport(fd);
165}
166
167static void udpread(void)
168{
169 char buf[BUFSIZE];
170 int ret = recv(sockfd, buf, BUFSIZE, 0);
171 if (ret < 0)
172 {
173 sockerror("recv (udp)");
174 x_closesocket(sockfd);
175 exit(1);
176 }
177 else if (ret > 0)
178 {
179#ifdef UNIX
180 if (write(1, buf, ret) < ret)
181 {
182 perror("write");
183 exit(1);
184 }
185#else
186 int j;
187 for (j = 0; j < ret; j++)
188 putchar(buf[j]);
189#endif
190 }
191}
192
193static int tcpmakeoutput(t_fdpoll *x)
194{
195 char messbuf[BUFSIZE+1], *bp = messbuf;
196 int indx;
197 int inhead = x->fdp_inhead;
198 int intail = x->fdp_intail;
199 char *inbuf = x->fdp_inbuf;
200 if (intail == inhead)
201 return (0);
202 for (indx = intail; indx != inhead; indx = (indx+1)&(BUFSIZE-1))
203 {
204 /* search for a semicolon. */
205 char c = *bp++ = inbuf[indx];
206 if (c == ';')
207 {
208 intail = (indx+1)&(BUFSIZE-1);
209 if (inbuf[intail] == '\n')
210 intail = (intail+1)&(BUFSIZE-1);
211 *bp++ = '\n';
212#ifdef UNIX
213 write(1, messbuf, bp - messbuf);
214#else
215 {
216 int j;
217 for (j = 0; j < bp - messbuf; j++)
218 putchar(messbuf[j]);
219 }
220#endif
221 x->fdp_inhead = inhead;
222 x->fdp_intail = intail;
223 return (1);
224 }
225 }
226 return (0);
227}
228
229static void tcpread(t_fdpoll *x)
230{
231 int readto =
232 (x->fdp_inhead >= x->fdp_intail ? BUFSIZE : x->fdp_intail-1);
233 int ret;
234
235 /* the input buffer might be full. If so, drop the whole thing */
236 if (readto == x->fdp_inhead)
237 {
238 fprintf(stderr, "pd: dropped message from gui\n");
239 x->fdp_inhead = x->fdp_intail = 0;
240 readto = BUFSIZE;
241 }
242 else
243 {
244 ret = recv(x->fdp_fd, x->fdp_inbuf + x->fdp_inhead,
245 readto - x->fdp_inhead, 0);
246 if (ret < 0)
247 {
248 sockerror("recv (tcp)");
249 rmport(x);
250 }
251 else if (ret == 0)
252 rmport(x);
253 else
254 {
255 x->fdp_inhead += ret;
256 if (x->fdp_inhead >= BUFSIZE)
257 x->fdp_inhead = 0;
258 while (tcpmakeoutput(x))
259 ;
260 }
261 }
262}
263
264static void dopoll(void)
265{
266 int i;
267 t_fdpoll *fp;
268 fd_set readset, writeset, exceptset;
269 FD_ZERO(&writeset);
270 FD_ZERO(&readset);
271 FD_ZERO(&exceptset);
272
273 FD_SET(sockfd, &readset);
274 if (protocol == SOCK_STREAM)
275 {
276 for (fp = fdpoll, i = nfdpoll; i--; fp++)
277 FD_SET(fp->fdp_fd, &readset);
278 }
279 if (select(maxfd+1, &readset, &writeset, &exceptset, 0) < 0)
280 {
281 perror("select");
282 exit(1);
283 }
284 if (protocol == SOCK_STREAM)
285 {
286 for (i = 0; i < nfdpoll; i++)
287 if (FD_ISSET(fdpoll[i].fdp_fd, &readset))
288 tcpread(&fdpoll[i]);
289 if (FD_ISSET(sockfd, &readset))
290 doconnect();
291 }
292 else
293 {
294 if (FD_ISSET(sockfd, &readset))
295 udpread();
296 }
297}
298
299
300static void sockerror(char *s)
301{
302#ifdef MSW
303 int err = WSAGetLastError();
304 if (err == 10054) return;
305 else if (err == 10044)
306 {
307 fprintf(stderr,
308 "Warning: you might not have TCP/IP \"networking\" turned on\n");
309 }
310#endif
311#ifdef UNIX
312 int err = errno;
313#endif
314 fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err);
315}
316
317static void x_closesocket(int fd)
318{
319#ifdef UNIX
320 close(fd);
321#endif
322#ifdef MSW
323 closesocket(fd);
324#endif
325}
326/* Copyright (c) 2000 Miller Puckette.
327* For information on usage and redistribution, and for a DISCLAIMER OF ALL
328* WARRANTIES, see the file, "LICENSE.txt," in the Pd distribution. */
329
330/* the "pdreceive" command. This is a standalone program that receives messages
331from Pd via the netsend/netreceive ("FUDI") protocol, and copies them to
332standard output. */
333
334#include <sys/types.h>
335#include <string.h>
336#include <stdio.h>
337#include <errno.h>
338#include <stdlib.h>
339#ifdef UNIX
340#include <sys/time.h>
341#include <unistd.h>
342#include <sys/socket.h>
343#include <netinet/in.h>
344#include <netdb.h>
345#define SOCKET_ERROR -1
346#else
347#include <winsock.h>
348#endif
349
350typedef struct _fdpoll
351{
352 int fdp_fd;
353 char *fdp_inbuf;
354 int fdp_inhead;
355 int fdp_intail;
356 int fdp_udp;
357} t_fdpoll;
358
359static int nfdpoll;
360static t_fdpoll *fdpoll;
361static int maxfd;
362static int sockfd;
363static int protocol;
364
365static void sockerror(char *s);
366static void x_closesocket(int fd);
367static void dopoll(void);
368#define BUFSIZE 4096
369
370int main(int argc, char **argv)
371{
372 int portno;
373 struct sockaddr_in server;
374 int nretry = 10;
375#ifdef MSW
376 short version = MAKEWORD(2, 0);
377 WSADATA nobby;
378#endif
379 if (argc < 2 || sscanf(argv[1], "%d", &portno) < 1 || portno <= 0)
380 goto usage;
381 if (argc >= 3)
382 {
383 if (!strcmp(argv[2], "tcp"))
384 protocol = SOCK_STREAM;
385 else if (!strcmp(argv[2], "udp"))
386 protocol = SOCK_DGRAM;
387 else goto usage;
388 }
389 else protocol = SOCK_STREAM;
390#ifdef MSW
391 if (WSAStartup(version, &nobby)) sockerror("WSAstartup");
392#endif
393 sockfd = socket(AF_INET, protocol, 0);
394 if (sockfd < 0)
395 {
396 sockerror("socket()");
397 exit(1);
398 }
399 maxfd = sockfd + 1;
400 server.sin_family = AF_INET;
401 server.sin_addr.s_addr = INADDR_ANY;
402
403#ifdef IRIX
404 /* this seems to work only in IRIX but is unnecessary in
405 Linux. Not sure what MSW needs in place of this. */
406 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0)
407 post("setsockopt failed\n");
408#endif
409
410 /* assign client port number */
411 server.sin_port = htons((unsigned short)portno);
412
413 /* name the socket */
414 if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
415 {
416 sockerror("bind");
417 x_closesocket(sockfd);
418 return (0);
419 }
420 if (protocol == SOCK_STREAM)
421 {
422 if (listen(sockfd, 5) < 0)
423 {
424 sockerror("listen");
425 x_closesocket(sockfd);
426 exit(1);
427 }
428 }
429 /* now loop forever selecting on sockets */
430 while (1)
431 dopoll();
432
433usage:
434 fprintf(stderr, "usage: pdreceive <portnumber> [udp|tcp]\n");
435 fprintf(stderr, "(default is tcp)\n");
436 exit(1);
437}
438
439static void addport(int fd)
440{
441 int nfd = nfdpoll;
442 t_fdpoll *fp;
443 fdpoll = (t_fdpoll *)realloc(fdpoll,
444 (nfdpoll+1) * sizeof(t_fdpoll));
445 fp = fdpoll + nfdpoll;
446 fp->fdp_fd = fd;
447 nfdpoll++;
448 if (fd >= maxfd) maxfd = fd + 1;
449 fp->fdp_inhead = fp->fdp_intail = 0;
450 if (!(fp->fdp_inbuf = malloc(BUFSIZE)))
451 {
452 fprintf(stderr, "out of memory");
453 exit(1);
454 }
455 printf("number_connected %d;\n", nfdpoll);
456}
457
458static void rmport(t_fdpoll *x)
459{
460 int nfd = nfdpoll;
461 int i, size = nfdpoll * sizeof(t_fdpoll);
462 t_fdpoll *fp;
463 for (i = nfdpoll, fp = fdpoll; i--; fp++)
464 {
465 if (fp == x)
466 {
467 x_closesocket(fp->fdp_fd);
468 free(fp->fdp_inbuf);
469 while (i--)
470 {
471 fp[0] = fp[1];
472 fp++;
473 }
474 fdpoll = (t_fdpoll *)realloc(fdpoll,
475 (nfdpoll-1) * sizeof(t_fdpoll));
476 nfdpoll--;
477 printf("number_connected %d;\n", nfdpoll);
478 return;
479 }
480 }
481 fprintf(stderr, "warning: item removed from poll list but not found");
482}
483
484static void doconnect(void)
485{
486 int fd = accept(sockfd, 0, 0);
487 if (fd < 0)
488 perror("accept");
489 else addport(fd);
490}
491
492static void udpread(void)
493{
494 char buf[BUFSIZE];
495 int ret = recv(sockfd, buf, BUFSIZE, 0);
496 if (ret < 0)
497 {
498 sockerror("recv (udp)");
499 x_closesocket(sockfd);
500 exit(1);
501 }
502 else if (ret > 0)
503 {
504#ifdef UNIX
505 if (write(1, buf, ret) < ret)
506 {
507 perror("write");
508 exit(1);
509 }
510#else
511 int j;
512 for (j = 0; j < ret; j++)
513 putchar(buf[j]);
514#endif
515 }
516}
517
518static int tcpmakeoutput(t_fdpoll *x)
519{
520 char messbuf[BUFSIZE+1], *bp = messbuf;
521 int indx;
522 int inhead = x->fdp_inhead;
523 int intail = x->fdp_intail;
524 char *inbuf = x->fdp_inbuf;
525 if (intail == inhead)
526 return (0);
527 for (indx = intail; indx != inhead; indx = (indx+1)&(BUFSIZE-1))
528 {
529 /* search for a semicolon. */
530 char c = *bp++ = inbuf[indx];
531 if (c == ';')
532 {
533 intail = (indx+1)&(BUFSIZE-1);
534 if (inbuf[intail] == '\n')
535 intail = (intail+1)&(BUFSIZE-1);
536 *bp++ = '\n';
537#ifdef UNIX
538 write(1, messbuf, bp - messbuf);
539#else
540 {
541 int j;
542 for (j = 0; j < bp - messbuf; j++)
543 putchar(messbuf[j]);
544 }
545#endif
546 x->fdp_inhead = inhead;
547 x->fdp_intail = intail;
548 return (1);
549 }
550 }
551 return (0);
552}
553
554static void tcpread(t_fdpoll *x)
555{
556 int readto =
557 (x->fdp_inhead >= x->fdp_intail ? BUFSIZE : x->fdp_intail-1);
558 int ret;
559
560 /* the input buffer might be full. If so, drop the whole thing */
561 if (readto == x->fdp_inhead)
562 {
563 fprintf(stderr, "pd: dropped message from gui\n");
564 x->fdp_inhead = x->fdp_intail = 0;
565 readto = BUFSIZE;
566 }
567 else
568 {
569 ret = recv(x->fdp_fd, x->fdp_inbuf + x->fdp_inhead,
570 readto - x->fdp_inhead, 0);
571 if (ret < 0)
572 {
573 sockerror("recv (tcp)");
574 rmport(x);
575 }
576 else if (ret == 0)
577 rmport(x);
578 else
579 {
580 x->fdp_inhead += ret;
581 if (x->fdp_inhead >= BUFSIZE)
582 x->fdp_inhead = 0;
583 while (tcpmakeoutput(x))
584 ;
585 }
586 }
587}
588
589static void dopoll(void)
590{
591 int i;
592 t_fdpoll *fp;
593 fd_set readset, writeset, exceptset;
594 FD_ZERO(&writeset);
595 FD_ZERO(&readset);
596 FD_ZERO(&exceptset);
597
598 FD_SET(sockfd, &readset);
599 if (protocol == SOCK_STREAM)
600 {
601 for (fp = fdpoll, i = nfdpoll; i--; fp++)
602 FD_SET(fp->fdp_fd, &readset);
603 }
604 if (select(maxfd+1, &readset, &writeset, &exceptset, 0) < 0)
605 {
606 perror("select");
607 exit(1);
608 }
609 if (protocol == SOCK_STREAM)
610 {
611 for (i = 0; i < nfdpoll; i++)
612 if (FD_ISSET(fdpoll[i].fdp_fd, &readset))
613 tcpread(&fdpoll[i]);
614 if (FD_ISSET(sockfd, &readset))
615 doconnect();
616 }
617 else
618 {
619 if (FD_ISSET(sockfd, &readset))
620 udpread();
621 }
622}
623
624
625static void sockerror(char *s)
626{
627#ifdef MSW
628 int err = WSAGetLastError();
629 if (err == 10054) return;
630 else if (err == 10044)
631 {
632 fprintf(stderr,
633 "Warning: you might not have TCP/IP \"networking\" turned on\n");
634 }
635#endif
636#ifdef UNIX
637 int err = errno;
638#endif
639 fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err);
640}
641
642static void x_closesocket(int fd)
643{
644#ifdef UNIX
645 close(fd);
646#endif
647#ifdef MSW
648 closesocket(fd);
649#endif
650}