PageRenderTime 72ms CodeModel.GetById 19ms app.highlight 42ms RepoModel.GetById 0ms app.codeStats 1ms

/liblo-0.26/src/testlo.c

#
C | 1193 lines | 971 code | 159 blank | 63 comment | 335 complexity | 9d4d96a30c22302d6bb96bec1d07ff31 MD5 | raw file
Possible License(s): LGPL-2.1
   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/*
  18 * This is some testcase code - it exercises the internals of liblo, so its not
  19 * a good example to learn from, see examples/ for example code
  20 */
  21
  22#include <math.h>
  23#include <float.h>
  24#include <stdio.h>
  25#include <stdlib.h>
  26#include <string.h>
  27
  28#ifdef _MSC_VER
  29#define snprintf _snprintf
  30#else
  31#include <unistd.h>
  32#endif
  33
  34#include "lo_types_internal.h"
  35#include "lo_internal.h"
  36#include "lo/lo.h"
  37#include "config.h"
  38
  39#ifdef WIN32
  40#define PATHDELIM "\\"
  41#else
  42#define PATHDELIM "/"
  43#endif
  44
  45#ifndef MSG_NOSIGNAL
  46#define MSG_NOSIGNAL 0
  47#endif
  48
  49#define TEST(cond) if (!(cond)) { fprintf(stderr, "FAILED " #cond \
  50					  " at %s:%d\n", __FILE__, __LINE__); \
  51				  exit(1); } \
  52		   else { printf("passed " #cond "\n"); }
  53
  54union end_test32 {
  55    uint32_t i;
  56    char     c[4];
  57};
  58
  59union end_test64 {
  60    uint64_t i;
  61    char     c[8];
  62};
  63
  64static int done = 0;
  65static int bundle_count = 0;
  66static int pattern_count = 0;
  67static int reply_count = 0;
  68static int subtest_count = 0;
  69static int subtest_reply_count = 0;
  70static int error_okay = 0;
  71
  72char testdata[5] = "ABCDE";
  73
  74static int jitter_count = 0;
  75static float jitter_total = 0.0f;
  76static float jitter_max = 0.0f;
  77static float jitter_min = 1000.0f;
  78
  79void exitcheck(void);
  80void test_deserialise(void);
  81void test_validation(lo_address a);
  82void test_multicast(lo_server_thread st);
  83void error(int num, const char *m, const char *path);
  84void rep_error(int num, const char *m, const char *path);
  85
  86int generic_handler(const char *path, const char *types, lo_arg **argv,
  87		    int argc, lo_message data, void *user_data);
  88
  89int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
  90		 lo_message data, void *user_data);
  91
  92int reply_handler(const char *path, const char *types, lo_arg **argv, int argc,
  93		 lo_message data, void *user_data);
  94
  95int lots_handler(const char *path, const char *types, lo_arg **argv, int argc,
  96		 lo_message data, void *user_data);
  97
  98int coerce_handler(const char *path, const char *types, lo_arg **argv, int argc,
  99		 lo_message data, void *user_data);
 100
 101int bundle_handler(const char *path, const char *types, lo_arg **argv, int argc,
 102		 lo_message data, void *user_data);
 103
 104int timestamp_handler(const char *path, const char *types, lo_arg **argv, 
 105                 int argc, lo_message data, void *user_data);
 106
 107int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc,
 108		 lo_message data, void *user_data);
 109
 110int pattern_handler(const char *path, const char *types, lo_arg **argv,
 111	            int argc, lo_message data, void *user_data);
 112
 113int subtest_handler(const char *path, const char *types, lo_arg **argv,
 114	            int argc, lo_message data, void *user_data);
 115
 116int subtest_reply_handler(const char *path, const char *types, lo_arg **argv,
 117	            int argc, lo_message data, void *user_data);
 118
 119int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
 120		 lo_message data, void *user_data);
 121
 122int test_varargs(lo_address a, const char *path, const char *types, ...);
 123
 124int main()
 125{
 126    lo_blob btest = lo_blob_new(sizeof(testdata), testdata);
 127    lo_server_thread st, sta, stb;
 128    lo_server s = lo_server_new(NULL, error);
 129    lo_bundle b;
 130    lo_message m1, m2;
 131    char *server_url, *path, *protocol, *host, *port;
 132    const char *host2, *port2;
 133    lo_address a;
 134    uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00};
 135    union end_test32 et32;
 136    union end_test64 et64;
 137    lo_timetag tt = {0x1, 0x80000000}, sched;
 138    int count;
 139    int proto;
 140    char cmd[256];
 141
 142    test_deserialise();
 143
 144    sta = lo_server_thread_new("7591", error);
 145    stb = lo_server_thread_new("7591", rep_error);
 146    if (stb) {
 147	fprintf(stderr, "FAILED: create bad server thread object!\n");
 148	exit(1);
 149    }
 150    lo_server_thread_free(sta);
 151
 152    /* leak check */
 153    st = lo_server_thread_new(NULL, error);
 154    lo_server_thread_start(st);
 155#ifdef WIN32
 156    Sleep(4);
 157#else
 158    usleep(4000);
 159#endif
 160    lo_server_thread_stop(st);
 161    lo_server_thread_free(st);
 162    st = lo_server_thread_new(NULL, error);
 163    lo_server_thread_start(st);
 164    lo_server_thread_stop(st);
 165    lo_server_thread_free(st);
 166    st = lo_server_thread_new(NULL, error);
 167    lo_server_thread_free(st);
 168    st = lo_server_thread_new(NULL, error);
 169    lo_server_thread_free(st);
 170    st = lo_server_thread_new(NULL, error);
 171
 172    a = lo_address_new_from_url("osc://localhost/");
 173    TEST(a != NULL);
 174    lo_address_free(a);
 175
 176    a = lo_address_new_from_url("osc.://localhost/");
 177    TEST(a == NULL);
 178
 179
 180    atexit(exitcheck);
 181
 182    printf("type tests\n");
 183    TEST(sizeof(float) == sizeof(int32_t));
 184    TEST(sizeof(double) == sizeof(int64_t));
 185
 186    et32.i = 0x23242526U;
 187    et32.i = lo_htoo32(et32.i);
 188    if (et32.c[0] != 0x23 || et32.c[1] != 0x24 || et32.c[2] != 0x25 ||
 189	et32.c[3] != 0x26) {
 190	fprintf(stderr, "failed 32bit endian conversion test\n");
 191	fprintf(stderr, "0x23242526 -> %X\n", et32.i);
 192	exit(1);
 193    } else {
 194	printf("passed 32bit endian conversion test\n");
 195    }
 196
 197    et64.i = 0x232425262728292AULL;
 198    et64.i = lo_htoo64(et64.i);
 199    if (et64.c[0] != 0x23 || et64.c[1] != 0x24 || et64.c[2] != 0x25 ||
 200	et64.c[3] != 0x26 || et64.c[4] != 0x27 || et64.c[5] != 0x28 ||
 201	et64.c[6] != 0x29 || et64.c[7] != 0x2A) {
 202	fprintf(stderr, "failed 64bit endian conversion\n");
 203	fprintf(stderr, "0x232425262728292A -> %llX\n", (long long unsigned int)et64.i);
 204	exit(1);
 205    } else {
 206	printf("passed 64bit endian conversion\n");
 207    }
 208    printf("\n");
 209
 210    /* OSC URL tests */
 211    path = lo_url_get_path("osc.udp://localhost:9999/a/path/is/here");
 212    if (strcmp(path, "/a/path/is/here")) {
 213	printf("failed lo_url_get_path() test1\n");
 214	printf("'%s' != '/a/path/is/here'\n", path);
 215	exit(1);
 216    } else {
 217	printf("passed lo_url_get_path() test1\n");
 218    }
 219    free(path);
 220
 221    protocol = lo_url_get_protocol("osc.udp://localhost:9999/a/path/is/here");
 222    if (strcmp(protocol, "udp")) {
 223	printf("failed lo_url_get_protocol() test1\n");
 224	printf("'%s' != 'udp'\n", protocol);
 225	exit(1);
 226    } else {
 227	printf("passed lo_url_get_protocol() test1\n");
 228    }
 229    free(protocol);
 230
 231    protocol = lo_url_get_protocol("osc.tcp://localhost:9999/a/path/is/here");
 232    if (strcmp(protocol, "tcp")) {
 233	printf("failed lo_url_get_protocol() test2\n");
 234	printf("'%s' != 'tcp'\n", protocol);
 235	exit(1);
 236    } else {
 237	printf("passed lo_url_get_protocol() test2\n");
 238    }
 239    free(protocol);
 240    
 241    protocol = lo_url_get_protocol("osc.udp://[::ffff:localhost]:9999/a/path/is/here");
 242    if (strcmp(protocol, "udp")) {
 243	printf("failed lo_url_get_protocol() test1 (IPv6)\n");
 244	printf("'%s' != 'udp'\n", protocol);
 245	exit(1);
 246    } else {
 247	printf("passed lo_url_get_protocol() test1 (IPv6)\n");
 248    }
 249    free(protocol);
 250
 251    proto = lo_url_get_protocol_id("osc.udp://localhost:9999/a/path/is/here");
 252    if (proto != LO_UDP) {
 253	printf("failed lo_url_get_protocol_id() test1\n");
 254	printf("'%d' != LO_UDP\n", proto);
 255	exit(1);
 256    } else {
 257	printf("passed lo_url_get_protocol_id() test1\n");
 258    }
 259
 260    proto = lo_url_get_protocol_id("osc.tcp://localhost:9999/a/path/is/here");
 261    if (proto != LO_TCP) {
 262	printf("failed lo_url_get_protocol_id() test2\n");
 263	printf("'%d' != LO_TCP\n", proto);
 264	exit(1);
 265    } else {
 266	printf("passed lo_url_get_protocol_id() test2\n");
 267    }
 268    
 269    proto = lo_url_get_protocol_id("osc.invalid://localhost:9999/a/path/is/here");
 270    if (proto != -1) {
 271	printf("failed lo_url_get_protocol_id() test3\n");
 272	printf("'%d' != -1\n", proto);
 273	exit(1);
 274    } else {
 275	printf("passed lo_url_get_protocol_id() test3\n");
 276    }
 277    
 278    proto = lo_url_get_protocol_id("osc.udp://[::ffff:localhost]:9999/a/path/is/here");
 279    if (proto != LO_UDP) {
 280	printf("failed lo_url_get_protocol_id() test1 (IPv6)\n");
 281	printf("'%d' != LO_UDP\n", proto);
 282	exit(1);
 283    } else {
 284	printf("passed lo_url_get_protocol_id() test1 (IPv6)\n");
 285    }
 286
 287    host = lo_url_get_hostname("osc.udp://foo.example.com:9999/a/path/is/here");
 288    if (strcmp(host, "foo.example.com")) {
 289	printf("failed lo_url_get_hostname() test1\n");
 290	printf("'%s' != 'foo.example.com'\n", host);
 291	exit(1);
 292    } else {
 293	printf("passed lo_url_get_hostname() test1\n");
 294    }
 295    free(host);
 296
 297    host = lo_url_get_hostname("osc.udp://[0000::::0001]:9999/a/path/is/here");
 298    if (strcmp(host, "0000::::0001")) {
 299	printf("failed lo_url_get_hostname() test2 (IPv6)\n");
 300	printf("'%s' != '0000::::0001'\n", host);
 301	exit(1);
 302    } else {
 303	printf("passed lo_url_get_hostname() test2 (IPv6)\n");
 304    }
 305    free(host);
 306
 307    port = lo_url_get_port("osc.udp://localhost:9999/a/path/is/here");
 308    if (strcmp(port, "9999")) {
 309	printf("failed lo_url_get_port() test1\n");
 310	printf("'%s' != '9999'\n", port);
 311	exit(1);
 312    } else {
 313	printf("passed lo_url_get_port() test1\n");
 314    }
 315    free(port);
 316    
 317    port = lo_url_get_port("osc.udp://[::ffff:127.0.0.1]:9999/a/path/is/here");
 318    if (strcmp(port, "9999")) {
 319	printf("failed lo_url_get_port() test1 (IPv6)\n");
 320	printf("'%s' != '9999'\n", port);
 321	exit(1);
 322    } else {
 323	printf("passed lo_url_get_port() test1 (IPv6)\n");
 324    }
 325    free(port);
 326    printf("\n");
 327    
 328    
 329    
 330    
 331    
 332    a = lo_address_new_from_url("osc.tcp://foo.example.com:9999/");
 333    host2 = lo_address_get_hostname(a);
 334    if (strcmp(host2, "foo.example.com")) {
 335	printf("failed lo_address_get_hostname() test\n");
 336	printf("'%s' != 'foo.example.com'\n", host2);
 337	exit(1);
 338    } else {
 339	printf("passed lo_address_get_hostname() test\n");
 340    }
 341
 342    port2 = lo_address_get_port(a);
 343    if (strcmp(port2, "9999")) {
 344	printf("failed lo_address_get_port() test\n");
 345	printf("'%s' != '9999'\n", port2);
 346	exit(1);
 347    } else {
 348	printf("passed lo_address_get_port() test\n");
 349    }
 350
 351    proto = lo_address_get_protocol(a);
 352    if (proto != LO_TCP) {
 353	printf("failed lo_address_get_protocol() test\n");
 354	printf("'%d' != '%d'\n", proto, LO_TCP);
 355	exit(1);
 356    } else {
 357	printf("passed lo_address_get_protocol() test\n");
 358    }
 359
 360    server_url = lo_address_get_url(a);
 361    if (strcmp(server_url, "osc.tcp://foo.example.com:9999/")) {
 362	printf("failed lo_address_get_url() test\n");
 363	printf("'%s' != '%s'\n", server_url, "osc.tcp://foo.example.com:9999/");
 364	exit(1);
 365    } else {
 366	printf("passed lo_address_get_url() test\n");
 367    }
 368    free(server_url);
 369    lo_address_free( a );
 370    printf("\n");
 371    
 372
 373    /* Test blod sizes */
 374    if (lo_blob_datasize(btest) != 5 || lo_blobsize(btest) != 12) {
 375	printf("blob is %d (%d) bytes long, should be 5 (12)\n",
 376               lo_blob_datasize(btest), lo_blobsize(btest));
 377	lo_arg_pp(LO_BLOB, btest);
 378	printf(" <- blob\n");
 379	exit(1);
 380    }
 381    
 382    
 383    
 384    /* Server method handler tests */
 385    server_url = lo_server_thread_get_url(st);
 386    a = lo_address_new_from_url(server_url);
 387    printf("Server URL: %s\n", server_url);
 388    free(server_url);
 389
 390    /* add method that will match the path /foo/bar, with two numbers, coerced
 391     * to float and int */
 392
 393    lo_server_thread_add_method(st, "/foo/bar", "fi", foo_handler, lo_server_thread_get_server(st));
 394
 395    lo_server_thread_add_method(st, "/reply", "s", reply_handler, NULL);
 396
 397    lo_server_thread_add_method(st, "/lotsofformats", "fisbmhtdSccTFNI",
 398				lots_handler, NULL);
 399
 400    lo_server_thread_add_method(st, "/coerce", "dfhiSs",
 401				coerce_handler, NULL);
 402
 403    lo_server_thread_add_method(st, "/bundle", NULL,
 404				bundle_handler, NULL);
 405    lo_server_thread_add_method(st, "/timestamp", NULL,
 406				timestamp_handler, NULL);
 407    lo_server_thread_add_method(st, "/jitter", "ti",
 408				jitter_handler, NULL);
 409
 410    lo_server_thread_add_method(st, "/pattern/foo", NULL,
 411				pattern_handler, "foo");
 412    lo_server_thread_add_method(st, "/pattern/bar", NULL,
 413				pattern_handler, "bar");
 414    lo_server_thread_add_method(st, "/pattern/baz", NULL,
 415				pattern_handler, "baz");
 416
 417    lo_server_thread_add_method(st, "/subtest", "i",
 418				subtest_handler, st);
 419
 420    lo_server_thread_add_method(st, "/subtest-reply", "i",
 421				subtest_reply_handler, NULL);
 422
 423    /* add method that will match any path and args */
 424    lo_server_thread_add_method(st, NULL, NULL, generic_handler, NULL);
 425
 426    /* add method that will match the path /quit with no args */
 427    lo_server_thread_add_method(st, "/quit", "", quit_handler, NULL);
 428
 429    /* check that the thread restarts */
 430    lo_server_thread_start(st);
 431    lo_server_thread_stop(st);
 432    lo_server_thread_start(st);
 433
 434    if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
 435	printf("OSC error A %d: %s\n", lo_address_errno(a), lo_address_errstr(a));
 436	exit(1);
 437    }
 438
 439    if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
 440	printf("OSC error B %d: %s\n", lo_address_errno(a), lo_address_errstr(a));
 441	exit(1);
 442    }
 443
 444    test_validation(a);
 445    test_multicast(st);
 446
 447    lo_send(a, "/", "i", 242);
 448    lo_send(a, "/pattern/", "i", 243);
 449
 450#ifndef _MSC_VER  /* MS compiler refuses to compile this case */
 451    lo_send(a, "/bar", "ff", 0.12345678f, 1.0/0.0);
 452#endif
 453    lo_send(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123, "123",
 454	    btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym",
 455	    'X', 'Y');
 456    lo_send(a, "/coerce", "fdihsS", 0.1f, 0.2, 123, 124LL, "aaa", "bbb");
 457    lo_send(a, "/coerce", "ffffss", 0.1f, 0.2f, 123.0, 124.0, "aaa", "bbb");
 458    lo_send(a, "/coerce", "ddddSS", 0.1, 0.2, 123.0, 124.0, "aaa", "bbb");
 459    lo_send(a, "/a/b/c/d", "sfsff", "one", 0.12345678f, "three",
 460	    -0.00000023001f, 1.0);
 461    lo_send(a, "/a/b/c/d", "b", btest);
 462
 463    TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123,
 464                      "123", btest, midi_data, 0x0123456789abcdefULL, tt,
 465                      0.9999, "sym", 'X', 'Y', LO_ARGS_END) == 0);
 466
 467#ifdef __GNUC__
 468    // Note: Lack of support for variable-argument macros in non-GCC compilers
 469    //       does not allow us to test for these conditions.
 470
 471    // too many args
 472    TEST(test_varargs(a, "/lotsofformats", "f", 0.12345678f, 123,
 473                      "123", btest, midi_data, 0x0123456789abcdefULL, tt,
 474                      0.9999, "sym", 'X', 'Y', LO_ARGS_END) != 0);
 475    // too many types
 476    TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123,
 477                      "123", btest, midi_data, 0x0123456789abcdefULL, tt, 0.5,
 478                      LO_ARGS_END) != 0);
 479#endif
 480
 481    // test lo_message_add
 482    m1 = lo_message_new();
 483    TEST(lo_message_add(m1, "fisbmhtdSccTFNI", 0.12345678f, 123, "123",
 484                        btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym",
 485                        'X', 'Y') == 0);
 486    lo_send_message(a, "/lotsofformats", m1);
 487    lo_message_free(m1);
 488 
 489    lo_blob_free(btest);
 490
 491    lo_send(a, "/pattern/*", "s", "a");
 492    lo_send(a, "/pattern/ba[rz]", "s", "b");
 493
 494    server_url = lo_server_thread_get_url(st);
 495    sprintf(cmd, "." PATHDELIM "subtest %s &", server_url);
 496    if (system(cmd) != 0) {
 497	fprintf(stderr, "Cannot execute subtest command\n");
 498	exit(1);
 499    }
 500    system(cmd);
 501    free(server_url);
 502
 503#ifdef WIN32
 504    Sleep(2000);
 505#else
 506    sleep(2);
 507#endif
 508    TEST(reply_count == 3);
 509    TEST(pattern_count == 5);
 510    TEST(subtest_count == 2);
 511    TEST(subtest_reply_count == 22);
 512    printf("\n");
 513
 514    {
 515        lo_timetag t = {10,0xFFFFFFFC};
 516        b = lo_bundle_new(t);
 517    }
 518    m1 = lo_message_new();
 519    lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz");
 520    lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 521    lo_bundle_add_message(b, "/bundle", m1);
 522    lo_send_bundle(a, b);
 523
 524    /* This should be safe for multiple copies of the same message. */
 525    lo_bundle_free_messages(b);
 526
 527    {
 528        lo_timetag t = {1,2};
 529        b = lo_bundle_new(t);
 530    }
 531    m1 = lo_message_new();
 532    lo_message_add_int32(m1, 23);
 533    lo_message_add_string(m1, "23");
 534    lo_bundle_add_message(b, "/bundle", m1);
 535    m2 = lo_message_new();
 536    lo_message_add_string(m2, "24");
 537    lo_message_add_int32(m2, 24);
 538    lo_bundle_add_message(b, "/bundle", m2);
 539    lo_bundle_add_message(b, "/bundle", m1);
 540
 541/* 
 542    lo_send_bundle(a, b);
 543    if (a->errnum) {
 544	printf("error %d: %s\n", a->errnum, a->errstr);
 545	exit(1);
 546    }
 547*/
 548    TEST(lo_send_bundle(a, b) == 88);
 549
 550    /* Test freeing out-of-order copies of messages in a bundle. */
 551    lo_bundle_free_messages(b);
 552
 553    {
 554        lo_timetag t = {10,0xFFFFFFFE};
 555        b = lo_bundle_new(t);
 556    }
 557    m1 = lo_message_new();
 558    lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz");
 559    lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 560    lo_bundle_add_message(b, "/bundle", m1);
 561    lo_send_bundle(a, b);
 562    lo_message_free(m1);
 563    lo_bundle_free(b);
 564
 565    lo_timetag_now(&sched);
 566
 567    sched.sec += 5;
 568    b = lo_bundle_new(sched);
 569    m1 = lo_message_new();
 570    lo_message_add_string(m1, "future");
 571    lo_message_add_string(m1, "time");
 572    lo_message_add_string(m1, "test");
 573    lo_bundle_add_message(b, "/bundle", m1);
 574
 575    lo_send_bundle(a, b);
 576    lo_message_free(m1);
 577    lo_bundle_free(b);
 578
 579    lo_send_timestamped(a, sched, "/bundle", "s", "lo_send_timestamped() test");
 580
 581    /* test bundle timestamp ends up in message struct (and doesn't end up in
 582       unbundled messages) */
 583    lo_timetag_now(&sched);    
 584    lo_send_timestamped(a, sched, "/timestamp", "it", 1, sched);
 585    lo_send(a, "/timestamp", "it", 0, sched);
 586
 587#define JITTER_ITS 25
 588    /* jitter tests */
 589    {
 590	lo_timetag stamps[JITTER_ITS];
 591	lo_timetag now;
 592	int i;
 593
 594	for (i=0; i<JITTER_ITS; i++) {
 595	    lo_timetag_now(&now);
 596	    stamps[i] = now;
 597	    stamps[i].sec += 1;
 598	    stamps[i].frac = rand();
 599	    lo_send_timestamped(a, stamps[i], "/jitter", "ti", stamps[i], i);
 600	}
 601    }
 602
 603#ifdef WIN32
 604    Sleep(2000);
 605#else
 606    sleep(2);
 607#endif
 608
 609    lo_address_free(a);
 610
 611    TEST(lo_server_thread_events_pending(st));
 612
 613    while (lo_server_thread_events_pending(st)) {
 614	printf("pending events, wait...\n");
 615#ifdef WIN32
 616	fflush(stdout);
 617	Sleep(1000);
 618#else
 619	sleep(1);
 620#endif
 621    }
 622    
 623    TEST(bundle_count == 7);
 624    printf("\n");
 625
 626    printf("bundle timing jitter results:\n"
 627	   "max jitter = %fs\n"
 628	   "avg jitter = %fs\n"
 629           "min jitter = %fs\n\n",
 630           jitter_max, jitter_total/(float)jitter_count, jitter_min);
 631
 632    server_url = lo_server_get_url(s);
 633
 634    lo_server_add_method(s, NULL, NULL, generic_handler, NULL);
 635    a = lo_address_new_from_url(server_url);
 636    TEST(lo_server_recv_noblock(s, 0) == 0);
 637    printf("Testing noblock API on %s\n", server_url);
 638    lo_send(a, "/non-block-test", "f", 23.0);
 639
 640    count = 0;
 641    while (!lo_server_recv_noblock(s, 10) && count++ < 1000) { }
 642    if (count >= 1000) {
 643	printf("lo_server_recv_noblock() test failed\n");
 644
 645	exit(1);
 646    }
 647
 648    /* Delete methods */
 649    lo_server_thread_del_method(st, "/coerce", "dfhiSs");
 650    lo_server_del_method(s, NULL, NULL);
 651
 652    lo_address_free(a);
 653    lo_server_free(s);
 654    free(server_url);
 655
 656#ifndef WIN32
 657    { /* UNIX domain tests */
 658	lo_address ua;
 659	lo_server us;
 660	char *addr;
 661
 662	unlink("/tmp/testlo.osc");
 663	us = lo_server_new_with_proto("/tmp/testlo.osc", LO_UNIX, error);
 664	ua = lo_address_new_from_url("osc.unix:///tmp/testlo.osc");
 665	TEST(lo_server_get_protocol(us) == LO_UNIX);
 666	TEST(lo_send(ua, "/unix", "f", 23.0) == 16);
 667	TEST(lo_server_recv(us) == 16);
 668	addr = lo_server_get_url(us);
 669	TEST(!strcmp("osc.unix:////tmp/testlo.osc", addr));
 670	free(addr);
 671	lo_address_free(ua);
 672	ua = lo_address_new_with_proto(LO_UNIX, NULL, "/tmp/testlo.osc");
 673	TEST(lo_send(ua, "/unix", "f", 23.0) == 16);
 674	TEST(lo_server_recv(us) == 16);
 675	lo_server_free(us);
 676	lo_address_free(ua);
 677    }
 678#endif
 679
 680    { /* TCP tests */
 681	lo_address ta;
 682	lo_server ts;
 683	char *addr;
 684
 685	ts = lo_server_new_with_proto(NULL, LO_TCP, error);
 686	addr = lo_server_get_url(ts);
 687	ta = lo_address_new_from_url(addr);
 688	if (lo_address_errno(ta)) {
 689	    printf("err: %s\n", lo_address_errstr(ta));
 690	    exit(1);
 691	}
 692	TEST(lo_server_get_protocol(ts) == LO_TCP);
 693	TEST(lo_send(ta, "/tcp", "f", 23.0) == 16);
 694	TEST(lo_send(ta, "/tcp", "f", 23.0) == 16);
 695	TEST(lo_server_recv(ts) == 16);
 696	TEST(lo_server_recv(ts) == 16);
 697	free(addr);
 698	lo_server_free(ts);
 699	lo_address_free(ta);
 700    }
 701
 702    server_url = lo_server_thread_get_url(st);
 703    a = lo_address_new_from_url(server_url);
 704    /* exit */
 705    lo_send(a, "/quit", NULL);
 706    lo_address_free(a);
 707
 708    while (!done) {
 709#ifdef WIN32
 710    Sleep(1);
 711#else
 712	usleep(1000);
 713#endif
 714    }
 715
 716    lo_server_thread_free(st);
 717    free(server_url);
 718
 719
 720    return 0;
 721}
 722
 723void exitcheck(void)
 724{
 725    if (!done) {
 726	fprintf(stderr, "\ntest run not completed\n" PACKAGE_NAME
 727		" test FAILED\n");
 728    } else {
 729	printf(PACKAGE_NAME " test PASSED\n");
 730    }
 731}
 732
 733void error(int num, const char *msg, const char *path)
 734{
 735    printf("liblo server error %d in %s: %s", num, path, msg);
 736    if (!error_okay)
 737        exit(1);
 738    else
 739        printf(" (expected)\n");
 740}
 741
 742void rep_error(int num, const char *msg, const char *path)
 743{
 744    if (num != 9904) {
 745	error(num, msg, path);
 746    }
 747}
 748
 749int generic_handler(const char *path, const char *types, lo_arg **argv,
 750		    int argc, lo_message data, void *user_data)
 751{
 752    int i;
 753
 754    printf("path: <%s>\n", path);
 755    for (i=0; i<argc; i++) {
 756	printf("arg %d '%c' ", i, types[i]);
 757	lo_arg_pp(types[i], argv[i]);
 758	printf("\n");
 759    }
 760    printf("\n");
 761
 762    return 1;
 763}
 764
 765int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
 766		 lo_message data, void *user_data)
 767{
 768    lo_server serv = (lo_server)user_data;
 769    lo_address src = lo_message_get_source(data);
 770    char *url = lo_address_get_url(src);
 771    char *server_url = lo_server_get_url(serv);
 772    printf("Address of us: %s\n", server_url);
 773    printf("%s <- f:%f, i:%d\n", path, argv[0]->f, argv[1]->i);
 774    if (lo_send_from(src, serv, LO_TT_IMMEDIATE, "/reply", "s", "a reply") == -1) {
 775	printf("OSC reply error %d: %s\nSending to %s\n", lo_address_errno(src), lo_address_errstr(src), url);
 776	exit(1);
 777    } else {
 778	printf("Reply sent to %s\n\n", url);
 779    }
 780    free(server_url);
 781    free(url);
 782
 783    return 0;
 784}
 785
 786int reply_handler(const char *path, const char *types, lo_arg **argv, int argc,
 787		 lo_message data, void *user_data)
 788{
 789    lo_address src = lo_message_get_source(data);
 790    char *url = lo_address_get_url(src);
 791    printf("Reply received from %s\n", url);
 792    free(url);
 793    reply_count++;
 794
 795    return 0;
 796}
 797
 798int lots_handler(const char *path, const char *types, lo_arg **argv, int argc,
 799		 lo_message data, void *user_data)
 800{
 801    lo_blob b;
 802    unsigned char *d;
 803
 804    if (strcmp(path, "/lotsofformats")) {
 805	fprintf(stderr, "path != /lotsofformats\n");
 806	exit(1);
 807    }
 808    printf("path = %s\n", path);
 809    TEST(types[0] == 'f' && argv[0]->f == 0.12345678f);
 810    TEST(types[1] == 'i' && argv[1]->i == 123);
 811    TEST(types[2] == 's' && !strcmp(&argv[2]->s, "123"));
 812    b = (lo_blob)argv[3];
 813    d = lo_blob_dataptr(b);
 814    TEST(types[3] == 'b' && lo_blob_datasize(b) == 5);
 815    TEST(d[0] == 'A' && d[1] == 'B' && d[2] == 'C' && d[3] == 'D' &&
 816	 d[4] == 'E');
 817    d = argv[4]->m;
 818    TEST(d[0] == 0xff && d[1] == 0xf7 && d[2] == 0xaa && d[3] == 0x00);
 819    TEST(types[5] == 'h' && argv[5]->h == 0x0123456789ABCDEFULL);
 820    TEST(types[6] == 't' && argv[6]->t.sec == 1 && \
 821	 argv[6]->t.frac == 0x80000000);
 822    TEST(types[7] == 'd' && argv[7]->d == 0.9999);
 823    TEST(types[8] == 'S' && !strcmp(&argv[8]->S, "sym"));
 824printf("char: %d\n", argv[9]->c);
 825    TEST(types[9] == 'c' && argv[9]->c == 'X');
 826    TEST(types[10] == 'c' && argv[10]->c == 'Y');
 827    TEST(types[11] == 'T');
 828    TEST(types[12] == 'F');
 829    TEST(types[13] == 'N');
 830    TEST(types[14] == 'I');
 831
 832    printf("\n");
 833
 834    return 0;
 835}
 836
 837int coerce_handler(const char *path, const char *types, lo_arg **argv, int argc,
 838		 lo_message data, void *user_data)
 839{
 840    printf("path = %s\n", path);
 841    TEST(types[0] == 'd' && fabs(argv[0]->d - 0.1) < FLT_EPSILON);
 842    TEST(types[1] == 'f' && fabs(argv[1]->f - 0.2) < FLT_EPSILON);
 843    TEST(types[2] == 'h' && argv[2]->h == 123);
 844    TEST(types[3] == 'i' && argv[3]->i == 124);
 845    TEST(types[4] == 'S' && !strcmp(&argv[4]->S, "aaa"));
 846    TEST(types[5] == 's' && !strcmp(&argv[5]->s, "bbb"));
 847    printf("\n");
 848
 849    return 0;
 850}
 851
 852int bundle_handler(const char *path, const char *types, lo_arg **argv, int argc,
 853		 lo_message data, void *user_data)
 854{
 855    bundle_count++;
 856    printf("received bundle\n");
 857
 858    return 0;
 859}
 860
 861int timestamp_handler(const char *path, const char *types, lo_arg **argv, 
 862		      int argc, lo_message data, void *user_data)
 863{
 864    int bundled = argv[0]->i;
 865
 866    lo_timetag ts, arg_ts;
 867    ts = lo_message_get_timestamp(data);
 868    arg_ts = argv[1]->t;
 869
 870    if (bundled) {
 871      TEST((ts.sec == arg_ts.sec) && (ts.frac == arg_ts.frac));
 872    }
 873    else {
 874      TEST(ts.sec == LO_TT_IMMEDIATE.sec && ts.frac == LO_TT_IMMEDIATE.frac);
 875    }
 876    return 0;
 877}
 878
 879int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc,
 880                 lo_message data, void *user_data)
 881{
 882    lo_timetag now;
 883    float jitter;
 884
 885    lo_timetag_now(&now);
 886    jitter = fabs(lo_timetag_diff(now, argv[0]->t));
 887    jitter_count++;
 888    //printf("jitter: %f\n", jitter);
 889    printf("%d expected: %x:%x received %x:%x\n", argv[1]->i, argv[0]->t.sec,
 890	   argv[0]->t.frac, now.sec, now.frac);
 891    jitter_total += jitter;
 892    if (jitter > jitter_max) jitter_max = jitter;
 893    if (jitter < jitter_min) jitter_min = jitter;
 894
 895    return 0;
 896}
 897
 898int pattern_handler(const char *path, const char *types, lo_arg **argv,
 899		    int argc, lo_message data, void *user_data)
 900{
 901    pattern_count++;
 902    printf("pattern matched %s\n", (char *)user_data);
 903
 904    return 0;
 905}
 906
 907int subtest_handler(const char *path, const char *types, lo_arg **argv,
 908		    int argc, lo_message data, void *user_data)
 909{
 910    lo_address a = lo_message_get_source(data);
 911
 912    subtest_count++;
 913    printf("got subtest message %d\n", subtest_count);
 914    lo_send_from(a, lo_server_thread_get_server(user_data),
 915                 LO_TT_IMMEDIATE, "/subtest", "i", subtest_count);
 916
 917    return 0;
 918}
 919
 920int subtest_reply_handler(const char *path, const char *types, lo_arg **argv,
 921		    int argc, lo_message data, void *user_data)
 922{
 923    subtest_reply_count++;
 924    //printf("got subtest reply message %d\n", subtest_reply_count);
 925
 926    return 0;
 927}
 928
 929int quit_handler(const char *path, const char *types, lo_arg **argv, int argc,
 930		 lo_message data, void *user_data)
 931{
 932    done = 1;
 933
 934    return 0;
 935}
 936
 937int test_varargs(lo_address a, const char *path, const char *types, ...)
 938{
 939    va_list ap;
 940    lo_message m = lo_message_new();
 941    int error;
 942    va_start(ap, types);
 943    if ((error=lo_message_add_varargs(m, types, ap))==0)
 944        lo_send_message(a, path, m);
 945    else
 946        printf("lo_message_add_varargs returned %d\n", error);
 947    lo_message_free(m);
 948    return error<0;
 949}
 950
 951void replace_char(char *str, size_t size, const char find, const char replace)
 952{
 953    char *p = str;
 954    while(size--)
 955    {
 956        if (find == *p) { *p = replace; }
 957        ++p;
 958    }
 959}
 960
 961void test_deserialise()
 962{
 963    char *buf, *buf2, *tmp;
 964    const char *types = NULL, *path;
 965    lo_arg **argv = NULL;
 966    size_t len, size;
 967    char data[256];
 968    int result = 0;
 969
 970    lo_blob btest = lo_blob_new(sizeof(testdata), testdata);
 971    uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00};
 972    lo_timetag tt = {0x1, 0x80000000};
 973    lo_blob b = NULL;
 974
 975    // build a message
 976    lo_message msg = lo_message_new();
 977    TEST(0 == lo_message_get_argc(msg));
 978    lo_message_add_float(msg, 0.12345678f);             // 0  f
 979    lo_message_add_int32(msg, 123);                     // 1  i
 980    lo_message_add_string(msg, "123");                  // 2  s
 981    lo_message_add_blob(msg, btest);                    // 3  b
 982    lo_message_add_midi(msg, midi_data);                // 4  m
 983    lo_message_add_int64(msg, 0x0123456789abcdefULL);   // 5  h
 984    lo_message_add_timetag(msg, tt);                    // 6  t
 985    lo_message_add_double(msg, 0.9999);                 // 7  d
 986    lo_message_add_symbol(msg, "sym");                  // 8  S
 987    lo_message_add_char(msg, 'X');                      // 9  c
 988    lo_message_add_char(msg, 'Y');                      // 10 c
 989    lo_message_add_true(msg);                           // 11 T
 990    lo_message_add_false(msg);                          // 12 F
 991    lo_message_add_nil(msg);                            // 13 N
 992    lo_message_add_infinitum(msg);                      // 14 I
 993
 994    // test types, args
 995    TEST(15 == lo_message_get_argc(msg));
 996    types = lo_message_get_types(msg);
 997    TEST(NULL != types);
 998    argv = lo_message_get_argv(msg);
 999    TEST(NULL != argv);
1000    TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON);
1001    TEST('i' == types[1] && 123 == argv[1]->i);
1002    TEST('s' == types[2] && !strcmp(&argv[2]->s, "123"));
1003    TEST('b' == types[3]);
1004    b = (lo_blob)argv[3];
1005    TEST(lo_blob_datasize(b) == sizeof(testdata));
1006    TEST(12 == lo_blobsize(b));
1007    TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata)));
1008    TEST('m' == types[4]  && !memcmp(&argv[4]->m, midi_data, 4));
1009    TEST('h' == types[5]  && 0x0123456789abcdefULL == argv[5]->h);
1010    TEST('t' == types[6]  && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac);
1011    TEST('d' == types[7]  && fabs(argv[7]->d - 0.9999) < FLT_EPSILON);
1012    TEST('S' == types[8]  && !strcmp(&argv[8]->s, "sym"));
1013    TEST('c' == types[9]  && 'X' == argv[9]->c);
1014    TEST('c' == types[10] && 'Y' == argv[10]->c);
1015    TEST('T' == types[11] && NULL == argv[11]);
1016    TEST('F' == types[12] && NULL == argv[12]);
1017    TEST('N' == types[13] && NULL == argv[13]);
1018    TEST('I' == types[14] && NULL == argv[14]);
1019
1020    // serialise it
1021    len = lo_message_length(msg, "/foo");
1022    printf("serialise message_length=%d\n", (int)len);
1023    buf = calloc(len, sizeof(char));
1024    size = 0;
1025    tmp = lo_message_serialise(msg, "/foo", buf, &size);
1026    TEST(tmp == buf && size == len && 92 == len);
1027    lo_message_free(msg);
1028
1029    // deserialise it
1030    printf("deserialise\n");
1031    path = lo_get_path(buf, len);
1032    TEST(NULL != path && !strcmp(path, "/foo"));
1033    msg = lo_message_deserialise(buf, size, NULL);
1034    TEST(NULL != msg);
1035
1036    // repeat same test as above
1037    TEST(15 == lo_message_get_argc(msg));
1038    types = lo_message_get_types(msg);
1039    TEST(NULL != types);
1040    argv = lo_message_get_argv(msg);
1041    TEST(NULL != argv);
1042    TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON);
1043    TEST('i' == types[1] && 123 == argv[1]->i);
1044    TEST('s' == types[2] && !strcmp(&argv[2]->s, "123"));
1045    TEST('b' == types[3]);
1046    b = (lo_blob)argv[3];
1047    TEST(lo_blob_datasize(b) == sizeof(testdata));
1048    TEST(12 == lo_blobsize(b));
1049    TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata)));
1050    TEST('m' == types[4]  && !memcmp(&argv[4]->m, midi_data, 4));
1051    TEST('h' == types[5]  && 0x0123456789abcdefULL == argv[5]->h);
1052    TEST('t' == types[6]  && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac);
1053    TEST('d' == types[7]  && fabs(argv[7]->d - 0.9999) < FLT_EPSILON);
1054    TEST('S' == types[8]  && !strcmp(&argv[8]->s, "sym"));
1055    TEST('c' == types[9]  && 'X' == argv[9]->c);
1056    TEST('c' == types[10] && 'Y' == argv[10]->c);
1057    TEST('T' == types[11] && NULL == argv[11]);
1058    TEST('F' == types[12] && NULL == argv[12]);
1059    TEST('N' == types[13] && NULL == argv[13]);
1060    TEST('I' == types[14] && NULL == argv[14]);
1061
1062    // serialise it again, compare
1063    len = lo_message_length(msg, "/foo");
1064    printf("serialise message_length=%d\n", (int)len);
1065    buf2 = calloc(len, sizeof(char));
1066    size = 0;
1067    tmp = lo_message_serialise(msg, "/foo", buf2, &size);
1068    TEST(tmp == buf2 && size == len && 92 == len);
1069    TEST(!memcmp(buf, buf2, len));
1070    lo_message_free(msg);
1071
1072    lo_blob_free(btest);
1073    free(buf);
1074    free(buf2);
1075
1076    // deserialise failure tests with invalid message data
1077
1078    msg = lo_message_deserialise(data, 0, &result); // 0 size
1079    TEST(NULL == msg && LO_ESIZE == result);
1080
1081    snprintf(data, 256, "%s", "/foo"); // unterminated path string
1082    msg = lo_message_deserialise(data, 4, &result);
1083    TEST(NULL == msg && LO_EINVALIDPATH == result);
1084
1085    snprintf(data, 256, "%s", "/f_o"); // non-0 in pad area
1086    msg = lo_message_deserialise(data, 4, &result);
1087    TEST(NULL == msg && LO_EINVALIDPATH == result);
1088
1089    snprintf(data, 256, "%s", "/t__"); // types missing
1090    replace_char(data, 4, '_', '\0');
1091    msg = lo_message_deserialise(data, 4, &result);
1092    TEST(NULL == msg && LO_ENOTYPE == result);
1093
1094    snprintf(data, 256, "%s%s", "/t__", "____"); // types empty
1095    replace_char(data, 8, '_', '\0');
1096    msg = lo_message_deserialise(data, 8, &result);
1097    TEST(NULL == msg && LO_EBADTYPE == result);
1098
1099    snprintf(data, 256, "%s%s", "/t__", ",f_"); // short message
1100    replace_char(data, 7, '_', '\0');
1101    msg = lo_message_deserialise(data, 7, &result);
1102    TEST(NULL == msg && LO_EINVALIDTYPE == result);
1103
1104    snprintf(data, 256, "%s%s", "/t__", "ifi_"); // types missing comma
1105    replace_char(data, 8, '_', '\0');
1106    msg = lo_message_deserialise(data, 8, &result);
1107    TEST(NULL == msg && LO_EBADTYPE == result);
1108
1109    snprintf(data, 256, "%s%s", "/t__", ",ifi"); // types unterminated
1110    replace_char(data, 8, '_', '\0');
1111    msg = lo_message_deserialise(data, 8, &result);
1112    TEST(NULL == msg && LO_EINVALIDTYPE == result);
1113
1114    snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data
1115    replace_char(data, 8, '_', '\0');
1116    msg = lo_message_deserialise(data, 12, &result);
1117    TEST(NULL == msg && LO_EINVALIDARG == result);
1118
1119    snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data again
1120    replace_char(data, 8, '_', '\0');
1121    msg = lo_message_deserialise(data, 15, &result);
1122    TEST(NULL == msg && LO_EINVALIDARG == result);
1123
1124    snprintf(data, 256, "%s%s", "/t__", ",f__"); // too much arg data
1125    replace_char(data, 8, '_', '\0');
1126    msg = lo_message_deserialise(data, 16, &result);
1127    TEST(NULL == msg && LO_ESIZE == result);
1128
1129    snprintf(data, 256, "%s%s", "/t__", ",bs_"); // blob longer than msg length
1130    replace_char(data, 8, '_', '\0');
1131    *(uint32_t *)(data + 8) = lo_htoo32((uint32_t)99999);
1132    msg = lo_message_deserialise(data, 256, &result);
1133    TEST(NULL == msg && LO_EINVALIDARG == result);
1134}
1135
1136void test_validation(lo_address a)
1137{
1138    /* packet crafted to crash a lo_server when no input validation is performed */
1139    char mem[] = {"/\0\0\0,bs\0,\x00\x0F\x42\x3F"}; // OSC:  "/" ",bs" 999999
1140    int eok = error_okay;
1141    int sock = a->socket;
1142
1143    /* This code won't work with MSVC because the lo_client_sockets data structure
1144     * is not explicitly made available to external programs.  We could expose it
1145     * in debug mode, perhaps, but let's just skip this test for now.  (Can be tested
1146     * on Windows using MingW.) */
1147#ifdef _MSC_VER
1148    return;
1149#else
1150
1151    printf("validation\n");
1152
1153    if (sock == -1)
1154        sock = lo_client_sockets.udp;
1155    if (sock == -1) {
1156        fprintf(stderr, "Couldn't get socket in test_validation(), %s:%d\n", __FILE__, __LINE__);
1157        exit(1);
1158    }
1159
1160    error_okay = 1;
1161    if (sendto(sock, &mem, sizeof(mem), MSG_NOSIGNAL,
1162               a->ai->ai_addr, a->ai->ai_addrlen)==-1) {
1163        fprintf(stderr, "Error sending packet in test_validation(), %s:%d\n", __FILE__, __LINE__);
1164    }
1165#ifndef WIN32
1166    usleep(10000);
1167#else
1168    Sleep(10);
1169#endif
1170    error_okay = eok;
1171#endif
1172}
1173
1174void test_multicast(lo_server_thread st)
1175{
1176    /* test multicast server and sender */
1177    /* message is sent from st otherwise reply doesn't work */
1178    lo_server ms = lo_server_new_multicast("224.0.1.1", "15432", error);
1179    lo_address ma = lo_address_new("224.0.1.1", "15432");
1180    lo_address_set_ttl(ma, 1);
1181    lo_server_add_method(ms, "/foo/bar", "fi", foo_handler, ms);
1182    lo_server_add_method(ms, "/reply", "s", reply_handler, NULL);
1183    if (lo_send_from(ma, lo_server_thread_get_server(st), LO_TT_IMMEDIATE,
1184                     "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
1185        printf("multicast send error %d: %s\n", lo_address_errno(ma), lo_address_errstr(ma));
1186        exit(1);
1187    }
1188    TEST(lo_server_recv(ms)==24);
1189    lo_server_free(ms);
1190    lo_address_free(ma);
1191}
1192
1193/* vi:set ts=8 sts=4 sw=4: */