diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/u_pdreceive.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/u_pdreceive.c | 326 |
1 files changed, 0 insertions, 326 deletions
diff --git a/apps/plugins/pdbox/PDa/src/u_pdreceive.c b/apps/plugins/pdbox/PDa/src/u_pdreceive.c deleted file mode 100644 index 51e60f7d5f..0000000000 --- a/apps/plugins/pdbox/PDa/src/u_pdreceive.c +++ /dev/null | |||
@@ -1,326 +0,0 @@ | |||
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 | ||
6 | from Pd via the netsend/netreceive ("FUDI") protocol, and copies them to | ||
7 | standard 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 | |||
25 | typedef 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 | |||
34 | static int nfdpoll; | ||
35 | static t_fdpoll *fdpoll; | ||
36 | static int maxfd; | ||
37 | static int sockfd; | ||
38 | static int protocol; | ||
39 | |||
40 | static void sockerror(char *s); | ||
41 | static void x_closesocket(int fd); | ||
42 | static void dopoll(void); | ||
43 | #define BUFSIZE 4096 | ||
44 | |||
45 | int 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 | |||
108 | usage: | ||
109 | fprintf(stderr, "usage: pdreceive <portnumber> [udp|tcp]\n"); | ||
110 | fprintf(stderr, "(default is tcp)\n"); | ||
111 | exit(1); | ||
112 | } | ||
113 | |||
114 | static 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 | |||
133 | static 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 | |||
159 | static void doconnect(void) | ||
160 | { | ||
161 | int fd = accept(sockfd, 0, 0); | ||
162 | if (fd < 0) | ||
163 | perror("accept"); | ||
164 | else addport(fd); | ||
165 | } | ||
166 | |||
167 | static 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 | |||
193 | static 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 | |||
229 | static 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 | |||
264 | static 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 | |||
300 | static 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 | |||
317 | static void x_closesocket(int fd) | ||
318 | { | ||
319 | #ifdef UNIX | ||
320 | close(fd); | ||
321 | #endif | ||
322 | #ifdef MSW | ||
323 | closesocket(fd); | ||
324 | #endif | ||
325 | } | ||
326 | |||