Пример #1
0
void *lo_message_serialise(lo_message m, const char *path, void *to,
                           size_t * size)
{
    int i, argc;
    char *types, *ptr;
    size_t s = lo_message_length(m, path);

    if (size) {
        *size = s;
    }

    if (!to) {
        to = calloc(1, s);
    }
    memset((char *) to + lo_strsize(path) - 4, 0, 4);   // ensure zero-padding
    strcpy(to, path);
    memset((char *) to + lo_strsize(path) + lo_strsize(m->types) - 4, 0,
           4);
    strcpy((char *) to + lo_strsize(path), m->types);

    types = m->types + 1;
    ptr = (char *) to + lo_strsize(path) + lo_strsize(m->types);
    memcpy(ptr, m->data, m->datalen);

    argc = m->typelen - 1;
    for (i = 0; i < argc; ++i) {
        size_t len = lo_arg_size(types[i], ptr);
        lo_arg_network_endian(types[i], ptr);
        ptr += len;
    }
    return to;
}
Пример #2
0
int lo_coerce(lo_type type_to, lo_arg * to, lo_type type_from,
              lo_arg * from)
{
    if (type_to == type_from) {
        memcpy(to, from, lo_arg_size(type_from, from));

        return 1;
    }

    if (lo_is_string_type(type_to) && lo_is_string_type(type_from)) {
        strcpy((char *) to, (char *) from);

        return 1;
    }

    if (lo_is_numerical_type(type_to) && lo_is_numerical_type(type_from)) {
        switch (type_to) {
        case LO_INT32:
            to->i = (uint32_t) lo_hires_val(type_from, from);
            break;

        case LO_INT64:
            to->i64 = (uint64_t) lo_hires_val(type_from, from);
            break;

        case LO_FLOAT:
            to->f = (float) lo_hires_val(type_from, from);
            break;

        case LO_DOUBLE:
            to->d = (double) lo_hires_val(type_from, from);
            break;

        default:
            fprintf(stderr, "liblo: bad coercion: %c -> %c\n", type_from,
                    type_to);
            return 0;
        }
        return 1;
    }

    return 0;
}
Пример #3
0
void lo_message_pp(lo_message m)
{
    void *d = m->data;
    void *end = m->data + m->datalen;
    int i;

    printf("%s ", m->types);
    for (i = 1; m->types[i]; i++) {
	if (i > 1) {
	    printf(" ");
	}

	lo_arg_pp_internal(m->types[i], d, 1);
	d += lo_arg_size(m->types[i], d);
    }
    putchar('\n');
    if (d != end) {
	fprintf(stderr, "liblo warning: type and data do not match (off by %d) in message %p\n",
		abs(d - end), m);
    }
}
Пример #4
0
void lo_arg_pp_internal(lo_type type, void *data, int bigendian)
{
    lo_pcast32 val32;
    lo_pcast64 val64;
    int size;
    int i;

    size = lo_arg_size(type, data);
    if (size == 4 || type == LO_BLOB) {
	if (bigendian) {
	    val32.nl = lo_otoh32(*(int32_t *)data);
	} else {
	    val32.nl = *(int32_t *)data;
	}
    } else if (size == 8) {
	if (bigendian) {
	    val64.nl = lo_otoh64(*(int64_t *)data);
	} else {
	    val64.nl = *(int64_t *)data;
	}
    }

    switch (type) {
    case LO_INT32:
	printf("%d", val32.i);
	break;
    
    case LO_FLOAT:
	printf("%f", val32.f);
	break;

    case LO_STRING:
	printf("\"%s\"", (char *)data);
	break;

    case LO_BLOB:
	printf("[");
	if (val32.i > 12) {
	    printf("%d byte blob", val32.i);
	} else {
	    printf("%db ", val32.i);
	    for (i=0; i<val32.i; i++) {
		printf("0x%02x", *((char *)(data) + 4 + i));
		if (i+1 < val32.i) printf(" ");
	    }
	}
	printf("]");
	break;

    case LO_INT64:
	printf("%lld", val64.i);
	break;
    
    case LO_TIMETAG:
	printf("%08x.%08x", val64.tt.sec, val64.tt.frac);
	break;
    
    case LO_DOUBLE:
	printf("%f", val64.f);
	break;
    
    case LO_SYMBOL:
	printf("'%s", (char *)data);
	break;

    case LO_CHAR:
	printf("'%c'", (char)val32.c);
	break;

    case LO_MIDI:
	printf("MIDI [");
	for (i=0; i<4; i++) {
	    printf("0x%02x", *((uint8_t *)(data) + i));
	    if (i+1 < 4) printf(" ");
	}
	printf("]");
	break;

    case LO_TRUE:
	printf("#T");
	break;

    case LO_FALSE:
	printf("#F");
	break;

    case LO_NIL:
	printf("Nil");
	break;

    case LO_INFINITUM:
	printf("Infinitum");
	break;

    default:
	fprintf(stderr, "liblo warning: unhandled type: %c\n", type);
	break;
    }
}
Пример #5
0
static void dispatch_method(lo_server s, const char *path, char *types,
			    void *data)
{
    int argc = strlen(types);
    lo_arg **argv = NULL;
    lo_method it;
    int ret = 1;
    int err;
    int endian_fixed = 0;
    int pattern = strpbrk(path, " #*,?[]{}") != NULL;
    lo_message msg = lo_message_new();
    lo_address src = lo_address_new(NULL, NULL);
    char hostname[LO_HOST_SIZE];
    char portname[32];
    const char *pptr;

    free(msg->types);
    msg->types = types;
    msg->typelen = strlen(types);
    msg->typesize = 0;
    msg->data = data;
    msg->datalen = 0;
    msg->datasize = 0;
    msg->source = src;

    //inet_ntop(s->addr.ss_family, &s->addr.padding, hostname, sizeof(hostname));
    if (s->protocol == LO_UDP) {
	err = getnameinfo((struct sockaddr *)&s->addr, sizeof(s->addr),
	    hostname, sizeof(hostname), portname, sizeof(portname),
	    NI_NUMERICHOST | NI_NUMERICSERV);
	if (err) {
	    switch (err) {
	    case EAI_AGAIN:
		lo_throw(s, err, "Try again", path);
		break;
	    case EAI_BADFLAGS:
		lo_throw(s, err, "Bad flags", path);
		break;
	    case EAI_FAIL:
		lo_throw(s, err, "Failed", path);
		break;
	    case EAI_FAMILY:
		lo_throw(s, err, "Cannot resolve address family", path);
		break;
	    case EAI_MEMORY:
		lo_throw(s, err, "Out of memory", path);
		break;
	    case EAI_NONAME:
		lo_throw(s, err, "Cannot resolve", path);
		break;
#ifndef WIN32
	    case EAI_SYSTEM:
		lo_throw(s, err, strerror(err), path);
		break;
#endif
	    default:
		lo_throw(s, err, "Unknown error", path);
		break;
	    }

	    return;
	}
    } else {
	hostname[0] = '\0';
	portname[0] = '\0';
    }

    free(src->host);
    free(src->port);

    src->host = hostname;
    src->port = portname;
    src->proto = s->protocol;

    for (it = s->first; it; it = it->next) {
	/* If paths match or handler is wildcard */
	if (!it->path || !strcmp(path, it->path) ||
	    (pattern && lo_pattern_match(it->path, path))) {
	    /* If types match or handler is wildcard */
	    if (!it->typespec || !strcmp(types, it->typespec)) {

		if (!argv && *types) {
		    int i;
		    char *ptr = types - 1 + lo_strsize(types - 1);

		    argv = calloc(argc + 1, sizeof(lo_arg *));
		    if (!endian_fixed) {
			for (i=0; i<argc; i++) {
			    argv[i] = (lo_arg *)ptr;
			    lo_arg_host_endian(types[i], ptr);
			    ptr += lo_arg_size(types[i], ptr);
			}
			endian_fixed = 1;
		    }
		}

		/* Send wildcard path to generic handler, expanded path
		  to others.
		*/
		pptr = path;
		if (it->path) pptr = it->path;
		ret = it->handler(pptr, types, argv, argc, msg,
				      it->user_data);

	    } else if (lo_can_coerce_spec(types, it->typespec)) {
		int i;
		int opsize = 0;
		char *ptr = types - 1 + lo_strsize(types - 1);
		char *data_co, *data_co_ptr;

		argv = calloc(argc+1, sizeof(lo_arg *));
		for (i=0; i<argc; i++) {
		    opsize += lo_arg_size(it->typespec[i], ptr);
		    ptr += lo_arg_size(types[i], ptr);
		}

		data_co = malloc(opsize);
		data_co_ptr = data_co;
		ptr = types - 1 + lo_strsize(types - 1);
		for (i=0; i<argc; i++) {
		    argv[i] = (lo_arg *)data_co_ptr;
		    if (!endian_fixed) {
			lo_arg_host_endian(types[i], ptr);
		    }
		    lo_coerce(it->typespec[i], (lo_arg *)data_co_ptr,
			      types[i], (lo_arg *)ptr);
		    data_co_ptr += lo_arg_size(it->typespec[i], data_co_ptr);
		    ptr += lo_arg_size(types[i], ptr);
		}
		endian_fixed = 1;

		/* Send wildcard path to generic handler, expanded path
		  to others.
		*/
		pptr = path;
		if (it->path) pptr = it->path;
		ret = it->handler(pptr, it->typespec, argv, argc, msg,
				      it->user_data);
		free(argv);
		free(data_co);
		argv = NULL;
	    }

	    if (ret == 0 && !pattern) {
		break;
	    }
	}
    }

    /* If we find no matching methods, check for protocol level stuff */
    if (ret == 1 && s->protocol == LO_UDP) {
	char *pos = strrchr(path, '/');

	/* if its a method enumeration call */
	if (pos && *(pos+1) == '\0') {
	    lo_message reply = lo_message_new();
	    int len = strlen(path);
	    lo_strlist *sl = NULL, *slit, *slnew, *slend;

	    if (!strcmp(types, "i")) {
		lo_message_add_int32(reply, argv[0]->i);
	    }
	    lo_message_add_string(reply, path);

	    for (it = s->first; it; it = it->next) {
		/* If paths match */
		if (it->path && !strncmp(path, it->path, len)) {
		    char *tmp;
		    char *sec;

		    tmp = malloc(strlen(it->path + len) + 1);
		    strcpy(tmp, it->path + len);
#ifdef WIN32
            sec = strchr(tmp,'/');
#else
		    sec = index(tmp, '/');
#endif
		    if (sec) *sec = '\0';
		    slend = sl;
		    for (slit = sl; slit; slend = slit, slit = slit->next) {
			if (!strcmp(slit->str, tmp)) {
			    free(tmp);
			    tmp = NULL;
			    break;
			}
		    }
		    if (tmp) {
			slnew = calloc(1, sizeof(lo_strlist));
			slnew->str = tmp;
			slnew->next = NULL;
			if (!slend) {
			    sl = slnew;
			} else {
			    slend->next = slnew;
			}
		    }
		}
	    }

	    for (slit = sl; slit; slit = slit->next) {
		lo_message_add_string(reply, slit->str);
		free(slit->str);
	    }
	    lo_send_message(src, "#reply", reply);
	    lo_message_free(reply);
	}
    }

    free(argv);

    /* the address got assigned static stuff, hence not using address_free */
    free(src);

    /* these are already part of data and will be freed later */
    msg->data = NULL;
    msg->types = NULL;
    lo_message_free(msg);
}