CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

send.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2004 Steve Harris
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * $Id$
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <sys/types.h>
27
28 #ifdef _MSC_VER
29 #include <io.h>
30 #else
31 #include <unistd.h>
32 #endif
33
34 #ifdef WIN32
35 #include <winsock2.h>
36 #include <ws2tcpip.h>
37 #else
38 #include <netdb.h>
39 #include <sys/socket.h>
40 #include <sys/un.h>
41 #endif
42
43 #include "lo_types_internal.h"
44 #include "lo/lo.h"
45
46 #ifndef MSG_NOSIGNAL
47 #define MSG_NOSIGNAL 0
48 #endif
49
50 #ifdef WIN32
51 int initWSock();
52 #endif
53
54 #ifdef WIN32
55 #define geterror() WSAGetLastError()
56 #else
57 #define geterror() errno
58 #endif
59
60 static int resolve_address(lo_address a);
61 static int create_socket(lo_address a);
62 static int send_data(lo_address a, lo_server from, char *data, const size_t data_len);
63
64 // message.c
65 int lo_message_add_varargs_internal(lo_message m, const char *types, va_list ap,
66 const char *file, int line);
67
68
69
70 /* Don't call lo_send_internal directly, use lo_send, a macro wrapping this
71 * function with appropriate values for file and line */
72
73 #ifdef __GNUC__
74 int lo_send_internal(lo_address t, const char *file, const int line,
75 const char *path, const char *types, ...)
76 #else
77 int lo_send(lo_address t, const char *path, const char *types, ...)
78 #endif
79 {
80 va_list ap;
81 int ret;
82 #ifndef __GNUC__
83 const char *file = "";
84 int line = 0;
85 #endif
86
87 lo_message msg = lo_message_new();
88
89 t->errnum = 0;
90 t->errstr = NULL;
91
92 va_start(ap, types);
93 ret = lo_message_add_varargs_internal(msg, types, ap, file, line);
94
95 if (ret) {
96 lo_message_free(msg);
97 t->errnum = ret;
98 if (ret == -1) t->errstr = "unknown type";
99 else t->errstr = "bad format/args";
100 return ret;
101 }
102
103 ret = lo_send_message(t, path, msg);
104 lo_message_free(msg);
105
106 return ret;
107 }
108
109
110 /* Don't call lo_send_timestamped_internal directly, use lo_send_timestamped, a
111 * macro wrapping this function with appropriate values for file and line */
112
113 #ifdef __GNUC__
114 int lo_send_timestamped_internal(lo_address t, const char *file,
115 const int line, lo_timetag ts,
116 const char *path, const char *types, ...)
117 #else
118 int lo_send_timestamped(lo_address t, lo_timetag ts,
119 const char *path, const char *types, ...)
120 #endif
121 {
122 va_list ap;
123 int ret;
124
125 lo_message msg = lo_message_new();
126 lo_bundle b = lo_bundle_new(ts);
127
128 #ifndef __GNUC__
129 const char *file = "";
130 int line = 0;
131 #endif
132
133 t->errnum = 0;
134 t->errstr = NULL;
135
136 va_start(ap, types);
137 ret = lo_message_add_varargs_internal(msg, types, ap, file, line);
138
139 if (t->errnum) {
140 lo_message_free(msg);
141 return t->errnum;
142 }
143
144 lo_bundle_add_message(b, path, msg);
145 ret = lo_send_bundle(t, b);
146 lo_message_free(msg);
147 lo_bundle_free(b);
148
149 return ret;
150 }
151
152 /* Don't call lo_send_from_internal directly, use macros wrapping this
153 * function with appropriate values for file and line */
154
155 #ifdef __GNUC__
156 int lo_send_from_internal(lo_address to, lo_server from, const char *file,
157 const int line, lo_timetag ts,
158 const char *path, const char *types, ...)
159 #else
160 int lo_send_from(lo_address to, lo_server from, lo_timetag ts,
161 const char *path, const char *types, ...)
162 #endif
163 {
164 lo_bundle b = NULL;
165 va_list ap;
166 int ret;
167
168 #ifndef __GNUC__
169 const char *file = "";
170 int line = 0;
171 #endif
172
173 lo_message msg = lo_message_new();
174 if (ts.sec!=LO_TT_IMMEDIATE.sec || ts.frac!=LO_TT_IMMEDIATE.frac)
175 b = lo_bundle_new(ts);
176
177 // Clear any previous errors
178 to->errnum = 0;
179 to->errstr = NULL;
180
181 va_start(ap, types);
182 ret = lo_message_add_varargs_internal(msg, types, ap, file, line);
183
184 if (to->errnum) {
185 if (b) lo_bundle_free(b);
186 lo_message_free(msg);
187 return to->errnum;
188 }
189
190 if (b) {
191 lo_bundle_add_message(b, path, msg);
192 ret = lo_send_bundle_from(to, from, b);
193 } else {
194 ret = lo_send_message_from(to, from, path, msg);
195 }
196
197 // Free-up memory
198 lo_message_free(msg);
199 if (b) lo_bundle_free(b);
200
201 return ret;
202 }
203
204
205 #if 0
206
207 This (incomplete) function converts from printf-style formats to OSC typetags,
208 but I think its dangerous and mislieading so its not available at the moment.
209
210 static char *format_to_types(const char *format);
211
212 static char *format_to_types(const char *format)
213 {
214 const char *ptr;
215 char *types = malloc(sizeof(format) + 1);
216 char *out = types;
217 int inspec = 0;
218 int width = 0;
219 int number = 0;
220
221 if (!format) {
222 return NULL;
223 }
224
225 for (ptr = format; *ptr; ptr++) {
226 if (inspec) {
227 if (*ptr == 'l') {
228 width++;
229 } else if (*ptr >= '0' && *ptr <= '9') {
230 number *= 10;
231 number += *ptr - '0';
232 } else if (*ptr == 'd') {
233 if (width < 2 && number < 64) {
234 *out++ = LO_INT32;
235 } else {
236 *out++ = LO_INT64;
237 }
238 } else if (*ptr == 'f') {
239 if (width < 2 && number < 64) {
240 *out++ = LO_FLOAT;
241 } else {
242 *out++ = LO_DOUBLE;
243 }
244 } else if (*ptr == '%') {
245 fprintf(stderr, "liblo warning, unexpected '%%' in format\n");
246 inspec = 1;
247 width = 0;
248 number = 0;
249 } else {
250 fprintf(stderr, "liblo warning, unrecognised character '%c' "
251 "in format\n", *ptr);
252 }
253 } else {
254 if (*ptr == '%') {
255 inspec = 1;
256 width = 0;
257 number = 0;
258 } else if (*ptr == LO_TRUE || *ptr == LO_FALSE || *ptr == LO_NIL ||
259 *ptr == LO_INFINITUM) {
260 *out++ = *ptr;
261 } else {
262 fprintf(stderr, "liblo warning, unrecognised character '%c' "
263 "in format\n", *ptr);
264 }
265 }
266 }
267 *out++ = '\0';
268
269 return types;
270 }
271
272 #endif
273
274
275 static int resolve_address(lo_address a)
276 {
277 int ret;
278
279 if (a->protocol == LO_UDP || a->protocol == LO_TCP) {
280 struct addrinfo *ai;
281 struct addrinfo hints;
282
283 memset(&hints, 0, sizeof(hints));
284 #ifdef ENABLE_IPV6
285 hints.ai_family = PF_UNSPEC;
286 #else
287 hints.ai_family = PF_INET;
288 #endif
289 hints.ai_socktype = a->protocol == LO_UDP ? SOCK_DGRAM : SOCK_STREAM;
290
291 if ((ret = getaddrinfo(a->host, a->port, &hints, &ai))) {
292 a->errnum = ret;
293 a->errstr = gai_strerror(ret);
294 a->ai = NULL;
295 return -1;
296 }
297
298 a->ai = ai;
299 }
300
301 return 0;
302 }
303
304 static int create_socket(lo_address a)
305 {
306 if (a->protocol == LO_UDP || a->protocol == LO_TCP) {
307
308 a->socket = socket(a->ai->ai_family, a->ai->ai_socktype, 0);
309 if (a->socket == -1) {
310 a->errnum = geterror();
311 a->errstr = NULL;
312 return -1;
313 }
314
315 if (a->protocol == LO_TCP) {
316 // Only call connect() for TCP sockets - we use sendto() for UDP
317 if ((connect(a->socket, a->ai->ai_addr, a->ai->ai_addrlen))) {
318 a->errnum = geterror();
319 a->errstr = NULL;
320 close(a->socket);
321 a->socket = -1;
322 return -1;
323 }
324 }
325 // if UDP and destination address is broadcast allow broadcast on the
326 // socket
327 else if (a->protocol == LO_UDP && a->ai->ai_family == AF_INET)
328 {
329 // If UDP, and destination address is broadcast,
330 // then allow broadcast on the socket.
331 struct sockaddr_in* si = (struct sockaddr_in*)a->ai->ai_addr;
332 unsigned char* ip = (unsigned char*)&(si->sin_addr);
333
334 if (ip[0]==255 && ip[1]==255 && ip[2]==255 && ip[3]==255)
335 {
336 int opt = 1;
337 setsockopt(a->socket, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int));
338 }
339 }
340
341 }
342 #ifndef WIN32
343 else if (a->protocol == LO_UNIX) {
344 struct sockaddr_un sa;
345
346 a->socket = socket(PF_UNIX, SOCK_DGRAM, 0);
347 if (a->socket == -1) {
348 a->errnum = geterror();
349 a->errstr = NULL;
350 return -1;
351 }
352
353 sa.sun_family = AF_UNIX;
354 strncpy(sa.sun_path, a->port, sizeof(sa.sun_path)-1);
355
356 if ((connect(a->socket, (struct sockaddr *)&sa, sizeof(sa))) < 0) {
357 a->errnum = geterror();
358 a->errstr = NULL;
359 close(a->socket);
360 a->socket = -1;
361 return -1;
362 }
363 }
364 #endif
365 else {
366 /* unknown protocol */
367 return -2;
368 }
369
370 return 0;
371 }
372
373 static int send_data(lo_address a, lo_server from, char *data, const size_t data_len)
374 {
375 int ret=0;
376 int sock=-1;
377
378 #ifdef WIN32
379 if(!initWSock()) return -1;
380 #endif
381
382 if (data_len > LO_MAX_MSG_SIZE) {
383 a->errnum = 99;
384 a->errstr = "Attempted to send message in excess of maximum "
385 "message size";
386 return -1;
387 }
388
389 // Resolve the destination address, if not done already
390 if (!a->ai) {
391 ret = resolve_address( a );
392 if (ret) return ret;
393 }
394
395 // Re-use existing socket?
396 if (from) {
397 sock = from->sockets[0].fd;
398 } else if (a->protocol == LO_UDP && lo_client_sockets.udp!=-1) {
399 sock = lo_client_sockets.udp;
400 } else {
401 if (a->socket==-1) {
402 ret = create_socket( a );
403 if (ret) return ret;
404 }
405 sock = a->socket;
406 }
407
408
409
410 // Send Length of the following data
411 if (a->protocol == LO_TCP) {
412 int32_t size = htonl(data_len);
413 ret = send(sock, &size, sizeof(size), MSG_NOSIGNAL);
414 }
415
416 // Send the data
417 if (a->protocol == LO_UDP) {
418 if (a->ttl >= 0) {
419 unsigned char ttl = (unsigned char)a->ttl;
420 setsockopt(sock,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl));
421 }
422 ret = sendto(sock, data, data_len, MSG_NOSIGNAL,
423 a->ai->ai_addr, a->ai->ai_addrlen);
424 } else {
425 ret = send(sock, data, data_len, MSG_NOSIGNAL);
426 }
427
428 if (a->protocol == LO_TCP && ret == -1) {
429 close(a->socket);
430 a->socket=-1;
431 }
432
433 if (ret == -1) {
434 a->errnum = geterror();
435 a->errstr = NULL;
436 } else {
437 a->errnum = 0;
438 a->errstr = NULL;
439 }
440
441 return ret;
442 }
443
444
445 int lo_send_message(lo_address a, const char *path, lo_message msg)
446 {
447 return lo_send_message_from( a, NULL, path, msg );
448 }
449
450 int lo_send_message_from(lo_address a, lo_server from, const char *path, lo_message msg)
451 {
452 const size_t data_len = lo_message_length(msg, path);
453 char *data = lo_message_serialise(msg, path, NULL, NULL);
454
455 // Send the message
456 int ret = send_data( a, from, data, data_len );
457
458 // For TCP, retry once if it failed. The first try will return
459 // error if the connection was closed, so the second try will
460 // attempt to re-open the connection.
461 if (ret == -1 && a->protocol == LO_TCP)
462 ret = send_data( a, from, data, data_len );
463
464 // Free the memory allocated by lo_message_serialise
465 if (data) free( data );
466
467 return ret;
468 }
469
470
471 int lo_send_bundle(lo_address a, lo_bundle b)
472 {
473 return lo_send_bundle_from( a, NULL, b );
474 }
475
476
477 int lo_send_bundle_from(lo_address a, lo_server from, lo_bundle b)
478 {
479 const size_t data_len = lo_bundle_length(b);
480 char *data = lo_bundle_serialise(b, NULL, NULL);
481
482 // Send the bundle
483 int ret = send_data( a, from, data, data_len );
484
485 // Free the memory allocated by lo_bundle_serialise
486 if (data) free( data );
487
488 return ret;
489 }
490
491 /* vi:set ts=8 sts=4 sw=4: */