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. */
5 /* the "pdreceive" command. This is a standalone program that receives messages
6 from Pd via the netsend/netreceive ("FUDI") protocol, and copies them to
17 #include <sys/socket.h>
18 #include <netinet/in.h>
20 #define SOCKET_ERROR -1
25 typedef struct _fdpoll
35 static t_fdpoll
*fdpoll
;
40 static void sockerror(char *s
);
41 static void x_closesocket(int fd
);
42 static void dopoll(void);
45 int main(int argc
, char **argv
)
48 struct sockaddr_in server
;
51 short version
= MAKEWORD(2, 0);
54 if (argc
< 2 || sscanf(argv
[1], "%d", &portno
) < 1 || portno
<= 0)
58 if (!strcmp(argv
[2], "tcp"))
59 protocol
= SOCK_STREAM
;
60 else if (!strcmp(argv
[2], "udp"))
61 protocol
= SOCK_DGRAM
;
64 else protocol
= SOCK_STREAM
;
66 if (WSAStartup(version
, &nobby
)) sockerror("WSAstartup");
68 sockfd
= socket(AF_INET
, protocol
, 0);
71 sockerror("socket()");
75 server
.sin_family
= AF_INET
;
76 server
.sin_addr
.s_addr
= INADDR_ANY
;
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");
85 /* assign client port number */
86 server
.sin_port
= htons((unsigned short)portno
);
89 if (bind(sockfd
, (struct sockaddr
*)&server
, sizeof(server
)) < 0)
92 x_closesocket(sockfd
);
95 if (protocol
== SOCK_STREAM
)
97 if (listen(sockfd
, 5) < 0)
100 x_closesocket(sockfd
);
104 /* now loop forever selecting on sockets */
109 fprintf(stderr
, "usage: pdreceive <portnumber> [udp|tcp]\n");
110 fprintf(stderr
, "(default is tcp)\n");
114 static void addport(int fd
)
118 fdpoll
= (t_fdpoll
*)realloc(fdpoll
,
119 (nfdpoll
+1) * sizeof(t_fdpoll
));
120 fp
= fdpoll
+ nfdpoll
;
123 if (fd
>= maxfd
) maxfd
= fd
+ 1;
124 fp
->fdp_inhead
= fp
->fdp_intail
= 0;
125 if (!(fp
->fdp_inbuf
= malloc(BUFSIZE
)))
127 fprintf(stderr
, "out of memory");
130 printf("number_connected %d;\n", nfdpoll
);
133 static void rmport(t_fdpoll
*x
)
136 int i
, size
= nfdpoll
* sizeof(t_fdpoll
);
138 for (i
= nfdpoll
, fp
= fdpoll
; i
--; fp
++)
142 x_closesocket(fp
->fdp_fd
);
149 fdpoll
= (t_fdpoll
*)realloc(fdpoll
,
150 (nfdpoll
-1) * sizeof(t_fdpoll
));
152 printf("number_connected %d;\n", nfdpoll
);
156 fprintf(stderr
, "warning: item removed from poll list but not found");
159 static void doconnect(void)
161 int fd
= accept(sockfd
, 0, 0);
167 static void udpread(void)
170 int ret
= recv(sockfd
, buf
, BUFSIZE
, 0);
173 sockerror("recv (udp)");
174 x_closesocket(sockfd
);
180 if (write(1, buf
, ret
) < ret
)
187 for (j
= 0; j
< ret
; j
++)
193 static int tcpmakeoutput(t_fdpoll
*x
)
195 char messbuf
[BUFSIZE
+1], *bp
= messbuf
;
197 int inhead
= x
->fdp_inhead
;
198 int intail
= x
->fdp_intail
;
199 char *inbuf
= x
->fdp_inbuf
;
200 if (intail
== inhead
)
202 for (indx
= intail
; indx
!= inhead
; indx
= (indx
+1)&(BUFSIZE
-1))
204 /* search for a semicolon. */
205 char c
= *bp
++ = inbuf
[indx
];
208 intail
= (indx
+1)&(BUFSIZE
-1);
209 if (inbuf
[intail
] == '\n')
210 intail
= (intail
+1)&(BUFSIZE
-1);
213 write(1, messbuf
, bp
- messbuf
);
217 for (j
= 0; j
< bp
- messbuf
; j
++)
221 x
->fdp_inhead
= inhead
;
222 x
->fdp_intail
= intail
;
229 static void tcpread(t_fdpoll
*x
)
232 (x
->fdp_inhead
>= x
->fdp_intail
? BUFSIZE
: x
->fdp_intail
-1);
235 /* the input buffer might be full. If so, drop the whole thing */
236 if (readto
== x
->fdp_inhead
)
238 fprintf(stderr
, "pd: dropped message from gui\n");
239 x
->fdp_inhead
= x
->fdp_intail
= 0;
244 ret
= recv(x
->fdp_fd
, x
->fdp_inbuf
+ x
->fdp_inhead
,
245 readto
- x
->fdp_inhead
, 0);
248 sockerror("recv (tcp)");
255 x
->fdp_inhead
+= ret
;
256 if (x
->fdp_inhead
>= BUFSIZE
)
258 while (tcpmakeoutput(x
))
264 static void dopoll(void)
268 fd_set readset
, writeset
, exceptset
;
273 FD_SET(sockfd
, &readset
);
274 if (protocol
== SOCK_STREAM
)
276 for (fp
= fdpoll
, i
= nfdpoll
; i
--; fp
++)
277 FD_SET(fp
->fdp_fd
, &readset
);
279 if (select(maxfd
+1, &readset
, &writeset
, &exceptset
, 0) < 0)
284 if (protocol
== SOCK_STREAM
)
286 for (i
= 0; i
< nfdpoll
; i
++)
287 if (FD_ISSET(fdpoll
[i
].fdp_fd
, &readset
))
289 if (FD_ISSET(sockfd
, &readset
))
294 if (FD_ISSET(sockfd
, &readset
))
300 static void sockerror(char *s
)
303 int err
= WSAGetLastError();
304 if (err
== 10054) return;
305 else if (err
== 10044)
308 "Warning: you might not have TCP/IP \"networking\" turned on\n");
314 fprintf(stderr
, "%s: %s (%d)\n", s
, strerror(err
), err
);
317 static void x_closesocket(int fd
)