Fix some greedy sed changes in imported code. Also provide a sys/types.h for compatib...
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / u_pdreceive.c
blob51e60f7d5fe1e024fd53d996fab3ab29df8b36b8
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
7 standard output. */
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
25 typedef struct _fdpoll
27 int fdp_fd;
28 char *fdp_inbuf;
29 int fdp_inhead;
30 int fdp_intail;
31 int fdp_udp;
32 } t_fdpoll;
34 static int nfdpoll;
35 static t_fdpoll *fdpoll;
36 static int maxfd;
37 static int sockfd;
38 static int protocol;
40 static void sockerror(char *s);
41 static void x_closesocket(int fd);
42 static void dopoll(void);
43 #define BUFSIZE 4096
45 int main(int argc, char **argv)
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)
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;
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)
71 sockerror("socket()");
72 exit(1);
74 maxfd = sockfd + 1;
75 server.sin_family = AF_INET;
76 server.sin_addr.s_addr = INADDR_ANY;
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
85 /* assign client port number */
86 server.sin_port = htons((unsigned short)portno);
88 /* name the socket */
89 if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
91 sockerror("bind");
92 x_closesocket(sockfd);
93 return (0);
95 if (protocol == SOCK_STREAM)
97 if (listen(sockfd, 5) < 0)
99 sockerror("listen");
100 x_closesocket(sockfd);
101 exit(1);
104 /* now loop forever selecting on sockets */
105 while (1)
106 dopoll();
108 usage:
109 fprintf(stderr, "usage: pdreceive <portnumber> [udp|tcp]\n");
110 fprintf(stderr, "(default is tcp)\n");
111 exit(1);
114 static void addport(int fd)
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)))
127 fprintf(stderr, "out of memory");
128 exit(1);
130 printf("number_connected %d;\n", nfdpoll);
133 static void rmport(t_fdpoll *x)
135 int nfd = nfdpoll;
136 int i, size = nfdpoll * sizeof(t_fdpoll);
137 t_fdpoll *fp;
138 for (i = nfdpoll, fp = fdpoll; i--; fp++)
140 if (fp == x)
142 x_closesocket(fp->fdp_fd);
143 free(fp->fdp_inbuf);
144 while (i--)
146 fp[0] = fp[1];
147 fp++;
149 fdpoll = (t_fdpoll *)realloc(fdpoll,
150 (nfdpoll-1) * sizeof(t_fdpoll));
151 nfdpoll--;
152 printf("number_connected %d;\n", nfdpoll);
153 return;
156 fprintf(stderr, "warning: item removed from poll list but not found");
159 static void doconnect(void)
161 int fd = accept(sockfd, 0, 0);
162 if (fd < 0)
163 perror("accept");
164 else addport(fd);
167 static void udpread(void)
169 char buf[BUFSIZE];
170 int ret = recv(sockfd, buf, BUFSIZE, 0);
171 if (ret < 0)
173 sockerror("recv (udp)");
174 x_closesocket(sockfd);
175 exit(1);
177 else if (ret > 0)
179 #ifdef UNIX
180 if (write(1, buf, ret) < ret)
182 perror("write");
183 exit(1);
185 #else
186 int j;
187 for (j = 0; j < ret; j++)
188 putchar(buf[j]);
189 #endif
193 static int tcpmakeoutput(t_fdpoll *x)
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))
204 /* search for a semicolon. */
205 char c = *bp++ = inbuf[indx];
206 if (c == ';')
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
216 int j;
217 for (j = 0; j < bp - messbuf; j++)
218 putchar(messbuf[j]);
220 #endif
221 x->fdp_inhead = inhead;
222 x->fdp_intail = intail;
223 return (1);
226 return (0);
229 static void tcpread(t_fdpoll *x)
231 int readto =
232 (x->fdp_inhead >= x->fdp_intail ? BUFSIZE : x->fdp_intail-1);
233 int ret;
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;
240 readto = BUFSIZE;
242 else
244 ret = recv(x->fdp_fd, x->fdp_inbuf + x->fdp_inhead,
245 readto - x->fdp_inhead, 0);
246 if (ret < 0)
248 sockerror("recv (tcp)");
249 rmport(x);
251 else if (ret == 0)
252 rmport(x);
253 else
255 x->fdp_inhead += ret;
256 if (x->fdp_inhead >= BUFSIZE)
257 x->fdp_inhead = 0;
258 while (tcpmakeoutput(x))
264 static void dopoll(void)
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);
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)
281 perror("select");
282 exit(1);
284 if (protocol == SOCK_STREAM)
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();
292 else
294 if (FD_ISSET(sockfd, &readset))
295 udpread();
300 static void sockerror(char *s)
302 #ifdef MSW
303 int err = WSAGetLastError();
304 if (err == 10054) return;
305 else if (err == 10044)
307 fprintf(stderr,
308 "Warning: you might not have TCP/IP \"networking\" turned on\n");
310 #endif
311 #ifdef UNIX
312 int err = errno;
313 #endif
314 fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err);
317 static void x_closesocket(int fd)
319 #ifdef UNIX
320 close(fd);
321 #endif
322 #ifdef MSW
323 closesocket(fd);
324 #endif