diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/x_net.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/x_net.c | 362 |
1 files changed, 0 insertions, 362 deletions
diff --git a/apps/plugins/pdbox/PDa/src/x_net.c b/apps/plugins/pdbox/PDa/src/x_net.c index 5094661214..c4a004cc5c 100644 --- a/apps/plugins/pdbox/PDa/src/x_net.c +++ b/apps/plugins/pdbox/PDa/src/x_net.c | |||
@@ -361,366 +361,4 @@ void x_net_setup(void) | |||
361 | netreceive_setup(); | 361 | netreceive_setup(); |
362 | } | 362 | } |
363 | 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 | |||
386 | static t_class *netsend_class; | ||
387 | |||
388 | typedef struct _netsend | ||
389 | { | ||
390 | t_object x_obj; | ||
391 | int x_fd; | ||
392 | int x_protocol; | ||
393 | } t_netsend; | ||
394 | |||
395 | static 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 | |||
404 | static 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 | |||
468 | static 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 | |||
478 | static 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 | |||
527 | static void netsend_free(t_netsend *x) | ||
528 | { | ||
529 | netsend_disconnect(x); | ||
530 | } | ||
531 | |||
532 | static 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 | |||
547 | static t_class *netreceive_class; | ||
548 | |||
549 | typedef 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 | |||
559 | static void netreceive_notify(t_netreceive *x) | ||
560 | { | ||
561 | outlet_float(x->x_connectout, --x->x_nconnections); | ||
562 | } | ||
563 | |||
564 | static 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 | |||
600 | static 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 | |||
614 | static 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 | |||
703 | static 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 | |||
713 | static 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 | |||
721 | void x_net_setup(void) | ||
722 | { | ||
723 | netsend_setup(); | ||
724 | netreceive_setup(); | ||
725 | } | ||
726 | 364 | ||