CSL  5.2
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
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
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 
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 
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 
472 {
473  return lo_send_bundle_from( a, NULL, b );
474 }
475 
476 
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: */