annotate src/liblo-0.26/src/send.c @ 124:e3d5853d5918

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