diff options
Diffstat (limited to 'src/pulsecore/parseaddr.c')
-rw-r--r-- | src/pulsecore/parseaddr.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c new file mode 100644 index 0000000..b909f52 --- /dev/null +++ b/src/pulsecore/parseaddr.c @@ -0,0 +1,156 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio 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. + + PulseAudio 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. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <stdlib.h> + +#include <pulse/xmalloc.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/macro.h> +#include <pulsecore/arpa-inet.h> + +#include "parseaddr.h" + +/* Parse addresses in one of the following forms: + * HOSTNAME + * HOSTNAME:PORT + * [HOSTNAME] + * [HOSTNAME]:PORT + * + * Return a newly allocated string of the hostname and fill in *ret_port if specified */ + +static char *parse_host(const char *s, uint16_t *ret_port) { + pa_assert(s); + pa_assert(ret_port); + + if (*s == '[') { + char *e; + if (!(e = strchr(s+1, ']'))) + return NULL; + + if (e[1] == ':') { + uint32_t p; + + if (pa_atou(e+2, &p) < 0) + return NULL; + + *ret_port = (uint16_t) p; + } else if (e[1] != 0) + return NULL; + + return pa_xstrndup(s+1, (size_t) (e-s-1)); + } else { + char *e; + uint32_t p; + + if (!(e = strrchr(s, ':'))) + return pa_xstrdup(s); + + if (pa_atou(e+1, &p) < 0) + return NULL; + + *ret_port = (uint16_t) p; + return pa_xstrndup(s, (size_t) (e-s)); + } +} + +int pa_parse_address(const char *name, pa_parsed_address *ret_p) { + const char *p; + + pa_assert(name); + pa_assert(ret_p); + + memset(ret_p, 0, sizeof(pa_parsed_address)); + ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO; + + if (*name == '{') { + char *id, *pfx; + + /* The URL starts with a host id for detecting local connections */ + if (!(id = pa_machine_id())) + return -1; + + pfx = pa_sprintf_malloc("{%s}", id); + pa_xfree(id); + + if (!pa_startswith(name, pfx)) { + pa_xfree(pfx); + /* Not local */ + return -1; + } + + p = name + strlen(pfx); + pa_xfree(pfx); + } else + p = name; + + if (*p == '/') + ret_p->type = PA_PARSED_ADDRESS_UNIX; + else if (pa_startswith(p, "unix:")) { + ret_p->type = PA_PARSED_ADDRESS_UNIX; + p += sizeof("unix:")-1; + } else if (pa_startswith(p, "tcp:")) { + ret_p->type = PA_PARSED_ADDRESS_TCP4; + p += sizeof("tcp:")-1; + } else if (pa_startswith(p, "tcp4:")) { + ret_p->type = PA_PARSED_ADDRESS_TCP4; + p += sizeof("tcp4:")-1; + } else if (pa_startswith(p, "tcp6:")) { + ret_p->type = PA_PARSED_ADDRESS_TCP6; + p += sizeof("tcp6:")-1; + } + + if (ret_p->type == PA_PARSED_ADDRESS_UNIX) + ret_p->path_or_host = pa_xstrdup(p); + else + if (!(ret_p->path_or_host = parse_host(p, &ret_p->port))) + return -1; + + return 0; +} + +bool pa_is_ip_address(const char *a) { + char buf[INET6_ADDRSTRLEN]; + + pa_assert(a); + + if (inet_pton(AF_INET6, a, buf) >= 1) + return true; + + if (inet_pton(AF_INET, a, buf) >= 1) + return true; + + return false; +} + +bool pa_is_ip6_address(const char *a) { + char buf[INET6_ADDRSTRLEN]; + + pa_assert(a); + + if (inet_pton(AF_INET6, a, buf) >= 1) + return true; + + return false; +} |