/* * Copyright (C) 2004 Steve Harris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * $Id$ */ #include #include #include #include #ifdef _MSC_VER #include #define snprintf _snprintf #else #include #endif #ifdef WIN32 #include #include #else #include #include #endif #include "lo_types_internal.h" #include "lo.h" #include "config.h" lo_address lo_address_new_with_proto(int proto, const char *host, const char *port) { lo_address a; if(proto != LO_UDP && proto != LO_TCP && proto != LO_UNIX) return NULL; a = calloc(1, sizeof(struct _lo_address)); if(a == NULL) return NULL; a->ai = NULL; a->socket = -1; a->protocol = proto; switch(proto) { default: case LO_UDP: case LO_TCP: if (host) { a->host = strdup(host); } else { a->host = strdup("localhost"); } break; case LO_UNIX: a->host = strdup("localhost"); break; } if (port) { a->port = strdup(port); } else { a->port = NULL; } a->ttl = -1; return a; } lo_address lo_address_new(const char *host, const char *port) { return lo_address_new_with_proto(LO_UDP, host ,port); } lo_address lo_address_new_from_url(const char *url) { lo_address a; int protocol; char *host, *port, *proto; if (!url || !*url) { return NULL; } protocol = lo_url_get_protocol_id(url); if (protocol == LO_UDP || protocol == LO_TCP) { host = lo_url_get_hostname(url); port = lo_url_get_port(url); a = lo_address_new_with_proto(protocol, host, port); if(host) free(host); if(port) free(port); #ifndef WIN32 } else if (protocol == LO_UNIX) { port = lo_url_get_path(url); a = lo_address_new_with_proto(LO_UNIX, NULL, port); if(port) free(port); #endif } else { proto = lo_url_get_protocol(url); fprintf(stderr, PACKAGE_NAME ": protocol '%s' not supported by this " "version\n", proto); if(proto) free(proto); return NULL; } return a; } const char *lo_address_get_hostname(lo_address a) { if (!a) { return NULL; } return a->host; } int lo_address_get_protocol(lo_address a) { if (!a) { return -1; } return a->protocol; } const char *lo_address_get_port(lo_address a) { if (!a) { return NULL; } return a->port; } static const char* get_protocol_name(int proto) { switch(proto) { case LO_UDP: return "udp"; case LO_TCP: return "tcp"; #ifndef WIN32 case LO_UNIX: return "unix"; #endif } return NULL; } char *lo_address_get_url(lo_address a) { char *buf; int ret=0; int needquote = strchr(a->host, ':') ? 1 : 0; char *fmt; if (needquote) { fmt = "osc.%s://[%s]:%s/"; } else { fmt = "osc.%s://%s:%s/"; } #ifndef _MSC_VER ret = snprintf(NULL, 0, fmt, get_protocol_name(a->protocol), a->host, a->port); #endif if (ret <= 0) { /* this libc is not C99 compliant, guess a size */ ret = 1023; } buf = malloc((ret + 2) * sizeof(char)); snprintf(buf, ret+1, fmt, get_protocol_name(a->protocol), a->host, a->port); return buf; } void lo_address_free(lo_address a) { if (a) { if (a->socket != -1) { close(a->socket); } if (a->host) free(a->host); if (a->port) free(a->port); if (a->ai) freeaddrinfo(a->ai); free(a); } } int lo_address_errno(lo_address a) { return a->errnum; } const char *lo_address_errstr(lo_address a) { char *msg; if (a->errstr) { return a->errstr; } msg = strerror(a->errnum); if (msg) { return msg; } else { return "unknown error"; } return "unknown error"; } char *lo_url_get_protocol(const char *url) { char *protocol,*ret; if (!url) { return NULL; } protocol = malloc(strlen(url)); if (sscanf(url, "osc://%s", protocol)) { fprintf(stderr, PACKAGE_NAME " warning: no protocol specified in URL, " "assuming UDP.\n"); ret = strdup("udp"); } else if (sscanf(url, "osc.%[^:/[]", protocol)) { ret = strdup(protocol); } else { ret = NULL; } free(protocol); return ret; } int lo_url_get_protocol_id(const char *url) { if(!url) { return -1; } if(!strncmp(url, "osc:", 4)) { fprintf(stderr, PACKAGE_NAME " warning: no protocol specified in URL, " "assuming UDP.\n"); return LO_UDP; // should be LO_DEFAULT? } else if(!strncmp(url, "osc.udp:", 8)) { return LO_UDP; } else if(!strncmp(url, "osc.tcp:", 8)) { return LO_TCP; } else if(!strncmp(url, "osc.unix:", 9)) { return LO_UNIX; } return -1; } char *lo_url_get_hostname(const char *url) { char *hostname = malloc(strlen(url)); if (sscanf(url, "osc://%[^[:/]", hostname)) { return hostname; } if (sscanf(url, "osc.%*[^:/]://[%[^]/]]", hostname)) { return hostname; } if (sscanf(url, "osc.%*[^:/]://%[^[:/]", hostname)) { return hostname; } /* doesnt look like an OSC URL */ free(hostname); return NULL; } char *lo_url_get_port(const char *url) { char *port = malloc(strlen(url)); if (sscanf(url, "osc://%*[^:]:%[0-9]", port)) { return port; } if (sscanf(url, "osc.%*[^:]://%*[^:]:%[0-9]", port)) { return port; } if (sscanf(url, "osc://[%*[^]]]:%[0-9]", port)) { return port; } if (sscanf(url, "osc.%*[^:]://[%*[^]]]:%[0-9]", port)) { return port; } /* doesnt look like an OSC URL with port number */ free(port); return NULL; } char *lo_url_get_path(const char *url) { char *path = malloc(strlen(url)); if (sscanf(url, "osc://%*[^:]:%*[0-9]%s", path)) { return path; } if (sscanf(url, "osc.%*[^:]://%*[^:]:%*[0-9]%s", path) == 1) { return path; } if (sscanf(url, "osc.unix://%*[^/]%s", path) == 1) { return path; } if (sscanf(url, "osc.%*[^:]://%s", path)) { return path; } /* doesnt look like an OSC URL with port number and path*/ free(path); return NULL; } void lo_address_set_ttl(lo_address t, int ttl) { if (t->protocol == LO_UDP) t->ttl = ttl; } int lo_address_get_ttl(lo_address t) { return t->ttl; } /* vi:set ts=8 sts=4 sw=4: */