Пример #1
0
int prSymbol_matchOSCPattern(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b;
	int length;
	
	a = g->sp - 1;
	b = g->sp;
	if (!IsSym(a) || !IsSym(b)) return errWrongType;
//	int32 alen = slotRawSymbol(a)->length;
//	int32 blen = slotRawSymbol(b)->length;
//	length = sc_min(alen, blen);
	if (lo_pattern_match(slotRawSymbol(a)->name, slotRawSymbol(b)->name)) {
		SetTrue(a);
	} else {
		SetFalse(a);
	}
	return errNone;
}
Пример #2
0
void lo_server_del_method(lo_server s, const char *path,
			  const char *typespec)
{
    lo_method it, prev, next;
    int pattern = 0;

    if (!s->first) return;
    if (path) pattern = strpbrk(path, " #*,?[]{}") != NULL;

    it = s->first;
    prev = it;
    while (it) {
	/* incase we free it */
	next = it->next;

	/* If paths match or handler is wildcard */
	if ((it->path == path) ||
	    (path && it->path && !strcmp(path, it->path)) ||
	    (pattern && lo_pattern_match(it->path, path))) {
	    /* If types match or handler is wildcard */
	    if ((it->typespec == typespec) ||
		(typespec && it->typespec && !strcmp(typespec, it->typespec))
	        ) {
		/* Take care when removing the head. */
		if (it == s->first) {
		    s->first = it->next;
		} else {
		    prev->next = it->next;
		}
		next = it->next;
		free((void *)it->path);
		free((void *)it->typespec);
		free(it);
		it = prev;
	    }
	}
	prev = it;
	if (it) it = next;
    }
}
Пример #3
0
int lo_pattern_match(const char *str, const char *p)
{
    int negate;
    int match;
    char c;

    while (*p) {
        if (!*str && *p != '*')
            return false;

        switch (c = *p++) {

            case '*':
                while (*p == '*' && *p != '/')
                    p++;

                if (!*p)
                    return true;

//                if (*p != '?' && *p != '[' && *p != '\\')
                if (*p != '?' && *p != '[' && *p != '{')
                    while (*str && *p != *str)
                        str++;

                while (*str) {
                    if (lo_pattern_match(str, p))
                        return true;
                    str++;
                }
                return false;

            case '?':
                if (*str)
                    break;
                return false;
                /*
                 * set specification is inclusive, that is [a-z] is a, z and
                 * everything in between. this means [z-a] may be interpreted
                 * as a set that contains z, a and nothing in between.
                 */
            case '[':
                if (*p != NEGATE)
                    negate = false;
                else {
                    negate = true;
                    p++;
                }

                match = false;

                while (!match && (c = *p++)) {
                    if (!*p)
                        return false;
                    if (*p == '-') {    /* c-c */
                        if (!*++p)
                            return false;
                        if (*p != ']') {
                            if (*str == c || *str == *p ||
                                    (*str > c && *str < *p))
                                match = true;
                        }
                        else {      /* c-] */
                            if (*str >= c)
                                match = true;
                            break;
                        }
                    }
                    else {          /* cc or c] */
                        if (c == *str)
                            match = true;
                        if (*p != ']') {
                            if (*p == *str)
                                match = true;
                        }
                        else
                            break;
                    }
                }

                if (negate == match)
                    return false;
                /*
                 * if there is a match, skip past the cset and continue on
                 */
                while (*p && *p != ']')
                    p++;
                if (!*p++)  /* oops! */
                    return false;
                break;

                /*
                 * {astring,bstring,cstring}
                 */
            case '{':
                {
                    // *p is now first character in the {brace list}
                    const char *place = str;    // to backtrack
                    const char *remainder = p;  // to forwardtrack

                    // find the end of the brace list
                    while (*remainder && *remainder != '}')
                        remainder++;
                    if (!*remainder++)  /* oops! */
                        return false;

                    c = *p++;

                    while (c) {
                        if (c == ',') {
                            if(lo_pattern_match(str, remainder)) {
                                return true;
                            } else {
                                // backtrack on test string
                                str = place;
                                // continue testing,
                                // skip comma
                                if (!*p++)  // oops
                                    return false;
                            }
                        }
                        else if (c == '}') {
                            // continue normal pattern matching
                            if (!*p && !*str) return true;
                            str--; // str is incremented again below
                            break;
                        } else if (c == *str) {
                            str++;
                            if (!*str && *remainder) 
                                return false;
                        } else { // skip to next comma
                            str = place;
                            while (*p != ',' && *p != '}' && *p)
                                p++;
                            if (*p == ',')
                                p++;
                            else if (*p == '}') {
                                return false;
                            }
                        }
                        c = *p++;
                    }
                }

                break;

                /* Not part of OSC pattern matching
                   case '\\':
                   if (*p)
                   c = *p++;
                   */

            default:
                if (c != *str)
                    return false;
                break;

        }
        str++;
    }

    return !*str;
}
Пример #4
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);
}