aboutsummaryrefslogtreecommitdiff
path: root/udpreceive.c
blob: 6ad31c18d42dcd2633ed11d7fa6f8fb87afc6ca7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* udpreceive.c
 * copyright (c) 2010 IOhannes m zmölnig, IEM
 * copyright (c) 2006-2010 Martin Peach
 * copyright (c) Miller Puckette
 */

/*                                                                              */
/* A server for unidirectional communication from within Pd.                     */
/*                                                                              */
/* This program is free software; you can redistribute it and/or                */
/* modify it under the terms of the GNU General Public License                  */
/* as published by the Free Software Foundation; either version 2               */
/* of the License, or (at your option) any later version.                       */
/*                                                                              */
/* This program is distributed in the hope that it will be useful,              */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of               */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
/* GNU General Public License for more details.                                 */
/*                                                                              */
/* You should have received a copy of the GNU General Public License            */
/* along with this program; if not, write to the Free Software                  */
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
/*                                                                              */


#include "iemnet.h"
#ifndef _WIN32
# include <netinet/tcp.h>
#endif

/* ----------------------------- udpreceive ------------------------- */

static t_class *udpreceive_class;

typedef struct _udpreceive
{
  t_object  x_obj;
  t_outlet  *x_msgout;
  t_outlet  *x_addrout;
  int       x_connectsocket;
  t_iemnet_receiver*x_receiver;
} t_udpreceive;


static void udpreceive_read_callback(void*y,
				     t_iemnet_chunk*c, 
				     int argc, t_atom*argv) {
  t_udpreceive*x=(t_udpreceive*)y;
  if(argc) {
    iemnet__addrout(NULL, x->x_addrout, c->addr, c->port);
    outlet_list(x->x_msgout, gensym("list"), argc, argv);
  } else {
    post("nothing received");
  }
}

static void *udpreceive_new(t_floatarg fportno)
{
    t_udpreceive       *x;
    struct sockaddr_in server;
    int                sockfd, portno = fportno;
    int                intarg;

    /* create a socket */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    DEBUG("socket %d port %d", sockfd, portno);
    if (sockfd < 0)
    {
        sys_sockerror("udpreceive: socket");
        return (0);
    }
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;

    /* enable delivery of all multicast or broadcast (but not unicast)
    * UDP datagrams to all sockets bound to the same port */
    intarg = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
        (char *)&intarg, sizeof(intarg)) < 0)
        post("udpreceive: setsockopt (SO_REUSEADDR) failed");

    /* assign server port number */
    server.sin_port = htons((u_short)portno);

    /* name the socket */
    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        sys_sockerror("udpreceive: bind");
        sys_closesocket(sockfd);
        return (0);
    }

    x = (t_udpreceive *)pd_new(udpreceive_class);
    x->x_msgout = outlet_new(&x->x_obj, &s_anything);
    x->x_addrout = outlet_new(&x->x_obj, &s_list);
    x->x_connectsocket = sockfd;

    //    sys_addpollfn(x->x_connectsocket, (t_fdpollfn)udpreceive_read, x);

    x->x_receiver=iemnet__receiver_create(sockfd,
					  x, 
					  udpreceive_read_callback);

    return (x);
}

static void udpreceive_free(t_udpreceive *x)
{
  iemnet__receiver_destroy(x->x_receiver);
  x->x_connectsocket=0;
}

void udpreceive_setup(void)
{
    udpreceive_class = class_new(gensym("udpreceive"),
        (t_newmethod)udpreceive_new, (t_method)udpreceive_free,
        sizeof(t_udpreceive), CLASS_NOINLET, A_DEFFLOAT, 0);
}

/* end udpreceive.c */