summaryrefslogtreecommitdiffstats
path: root/polyp
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-12-15 01:02:50 +0000
committerLennart Poettering <lennart@poettering.net>2004-12-15 01:02:50 +0000
commit99e0779b51ccf4482dd35e78fe2f80744633004e (patch)
treedbcb8ccabe55118c59cd3653dcaac3d4b1a39b38 /polyp
parentbc5b917f93f39215b54593cc45228e97e14daec3 (diff)
* Publish server info in mDNS in addition to sinks/sources
* Split off address parser * Add port= argument to module-zeroconf-publish git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@324 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'polyp')
-rw-r--r--polyp/Makefile.am10
-rw-r--r--polyp/module-zeroconf-publish.c61
-rw-r--r--polyp/parseaddr.c112
-rw-r--r--polyp/parseaddr.h42
-rw-r--r--polyp/polyplib-browser.c1
-rw-r--r--polyp/socket-client.c108
-rw-r--r--polyp/util.c2
7 files changed, 242 insertions, 94 deletions
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 79accfe6..0c491ce5 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -87,6 +87,7 @@ modlib_LTLIBRARIES= \
libiochannel.la \
libsocket-server.la \
libsocket-client.la \
+ libparseaddr.la \
libpacket.la \
libpstream.la \
liboss-util.la \
@@ -228,7 +229,8 @@ polypaudio_SOURCES = idxset.c idxset.h \
polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
polypaudio_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS)
-polypaudio_LDFLAGS= $(AM_LDFLAGS) -export-dynamic -dlopen force #-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
+polypaudio_LDFLAGS= $(AM_LDFLAGS) -export-dynamic -dlopen force
+#q-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h
libprotocol_simple_la_LDFLAGS = -avoid-version
@@ -240,7 +242,10 @@ libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la $(LI
libsocket_client_la_SOURCES = socket-client.c socket-client.h
libsocket_client_la_LDFLAGS = -avoid-version
-libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la
+libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la
+
+libparseaddr_la_SOURCES = parseaddr.c parseaddr.h
+libparseaddr_la_LDFLAGS = -avoid-version
libpstream_la_SOURCES = pstream.c pstream.h
libpstream_la_LDFLAGS = -avoid-version
@@ -434,6 +439,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \
util.c util.h \
memblock.c memblock.h \
socket-client.c socket-client.h \
+ parseaddr.c parseaddr.h \
packet.c packet.h \
queue.c queue.h \
dynarray.c dynarray.h \
diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c
index c88ac766..511ceb47 100644
--- a/polyp/module-zeroconf-publish.c
+++ b/polyp/module-zeroconf-publish.c
@@ -41,15 +41,22 @@
#include "subscribe.h"
#include "dynarray.h"
#include "endianmacros.h"
+#include "modargs.h"
PA_MODULE_AUTHOR("Lennart Poettering")
PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher")
PA_MODULE_VERSION(PACKAGE_VERSION)
+PA_MODULE_USAGE("port=<IP port number>")
#define SERVICE_NAME_SINK "_polypaudio-sink._tcp"
#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp"
#define SERVICE_NAME_SERVER "_polypaudio-server._tcp"
+static const char* const valid_modargs[] = {
+ "port",
+ NULL
+};
+
struct service {
sw_discovery_oid oid;
char *name;
@@ -74,6 +81,9 @@ struct userdata {
struct pa_hashmap *services;
struct pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray;
struct pa_subscription *subscription;
+
+ uint16_t port;
+ sw_discovery_oid server_oid;
};
static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_status status, sw_discovery_oid oid, sw_opaque extra) {
@@ -127,7 +137,7 @@ static int publish_service(struct userdata *u, struct service *s) {
s->published = 0;
}
- snprintf(t, sizeof(t), "%s@%s", s->name, pa_get_host_name(hn, sizeof(hn)));
+ snprintf(t, sizeof(t), "Networked Audio device %s on %s", s->name, pa_get_host_name(hn, sizeof(hn)));
if (sw_text_record_init(&txt) != SW_OKAY) {
pa_log(__FILE__": sw_text_record_init() failed\n");
@@ -160,7 +170,7 @@ static int publish_service(struct userdata *u, struct service *s) {
if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t,
s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE,
- NULL, NULL, PA_NATIVE_DEFAULT_PORT, sw_text_record_bytes(txt), sw_text_record_len(txt),
+ NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt),
publish_reply, s, &s->oid) != SW_OKAY) {
pa_log(__FILE__": failed to register sink on zeroconf.\n");
goto finish;
@@ -171,7 +181,7 @@ static int publish_service(struct userdata *u, struct service *s) {
if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t,
s->autoload.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE,
- NULL, NULL, PA_NATIVE_DEFAULT_PORT, sw_text_record_bytes(txt), sw_text_record_len(txt),
+ NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt),
publish_reply, s, &s->oid) != SW_OKAY) {
pa_log(__FILE__": failed to register sink on zeroconf.\n");
goto finish;
@@ -375,13 +385,28 @@ fail:
int pa__init(struct pa_core *c, struct pa_module*m) {
struct userdata *u;
- uint32_t index;
+ uint32_t index, port = PA_NATIVE_DEFAULT_PORT;
struct pa_sink *sink;
struct pa_source *source;
struct pa_autoload_entry *autoload;
+ struct pa_modargs *ma = NULL;
+ char t[256], hn[256];
+ int free_txt = 0;
+ sw_text_record txt;
+
+ if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+ pa_log(__FILE__": failed to parse module arguments.\n");
+ goto fail;
+ }
+
+ if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port == 0 || port >= 0xFFFF) {
+ pa_log(__FILE__": invalid port specified.\n");
+ goto fail;
+ }
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
u->core = c;
+ u->port = (uint16_t) port;
if (!(u->howl_wrapper = pa_howl_wrapper_get(c)))
goto fail;
@@ -409,10 +434,38 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
if (publish_autoload(u, autoload) < 0)
goto fail;
+ snprintf(t, sizeof(t), "Networked Audio on %s", pa_get_host_name(hn, sizeof(hn)));
+
+ if (sw_text_record_init(&txt) != SW_OKAY) {
+ pa_log(__FILE__": sw_text_record_init() failed\n");
+ goto fail;
+ }
+ free_txt = 1;
+
+ txt_record_server_data(u->core, txt);
+
+ if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t,
+ SERVICE_NAME_SERVER,
+ NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt),
+ publish_reply, u, &u->server_oid) != SW_OKAY) {
+ pa_log(__FILE__": failed to register server on zeroconf.\n");
+ goto fail;
+ }
+
+ sw_text_record_fina(txt);
+ pa_modargs_free(ma);
+
return 0;
fail:
pa__done(c, m);
+
+ if (ma)
+ pa_modargs_free(ma);
+
+ if (free_txt)
+ sw_text_record_fina(txt);
+
return -1;
}
diff --git a/polyp/parseaddr.c b/polyp/parseaddr.c
new file mode 100644
index 00000000..05ed508b
--- /dev/null
+++ b/polyp/parseaddr.c
@@ -0,0 +1,112 @@
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio 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.
+
+ polypaudio 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 polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "xmalloc.h"
+#include "util.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) {
+ assert(s && ret_port);
+ if (*s == '[') {
+ char *e;
+ if (!(e = strchr(s+1, ']')))
+ return NULL;
+
+ if (e[1] == ':')
+ *ret_port = atoi(e+2);
+ else if (e[1] != 0)
+ return NULL;
+
+ return pa_xstrndup(s+1, e-s-1);
+ } else {
+ char *e;
+
+ if (!(e = strrchr(s, ':')))
+ return pa_xstrdup(s);
+
+ *ret_port = atoi(e+1);
+ return pa_xstrndup(s, e-s);
+ }
+}
+
+int pa_parse_address(const char *name, struct pa_parsed_address *ret_p) {
+ const char *p;
+ assert(name && ret_p);
+ memset(ret_p, 0, sizeof(struct pa_parsed_address));
+ ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO;
+
+ if (*name == '{') {
+ char hn[256], *pfx;
+ /* The URL starts with a host specification for detecting local connections */
+
+ if (!pa_get_host_name(hn, sizeof(hn)))
+ return -1;
+
+ pfx = pa_sprintf_malloc("{%s}", hn);
+ 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:") || pa_startswith(p, "tcp4:")) {
+ ret_p->type = PA_PARSED_ADDRESS_TCP4;
+ p += sizeof("tcp:")-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;
+}
diff --git a/polyp/parseaddr.h b/polyp/parseaddr.h
new file mode 100644
index 00000000..5ddc0351
--- /dev/null
+++ b/polyp/parseaddr.h
@@ -0,0 +1,42 @@
+#ifndef fooparseaddrhfoo
+#define fooparseaddrhfoo
+
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio 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.
+
+ polypaudio 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 polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <inttypes.h>
+
+enum pa_parsed_address_type {
+ PA_PARSED_ADDRESS_UNIX,
+ PA_PARSED_ADDRESS_TCP4,
+ PA_PARSED_ADDRESS_TCP6,
+ PA_PARSED_ADDRESS_TCP_AUTO
+};
+
+struct pa_parsed_address {
+ enum pa_parsed_address_type type;
+ char *path_or_host;
+ uint16_t port;
+};
+
+int pa_parse_address(const char *a, struct pa_parsed_address *ret_p);
+
+#endif
diff --git a/polyp/polyplib-browser.c b/polyp/polyplib-browser.c
index a1bd3fb7..7e56e2ce 100644
--- a/polyp/polyplib-browser.c
+++ b/polyp/polyplib-browser.c
@@ -221,7 +221,6 @@ static sw_result browse_reply(
switch (status) {
case SW_DISCOVERY_BROWSE_ADD_SERVICE: {
sw_discovery_oid oid;
- fprintf(stderr, "debug: new service: %s\n", name);
if (sw_discovery_resolve(b->discovery, 0, name, type, domain, resolve_reply, b, &oid) != SW_OKAY)
pa_log("sw_discovery_resolve() failed\n");
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index c58c7bd4..0581e553 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -39,6 +39,7 @@
#include "util.h"
#include "xmalloc.h"
#include "log.h"
+#include "parseaddr.h"
struct pa_socket_client {
int ref;
@@ -254,121 +255,56 @@ struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, ui
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
}
-/* 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 *port if specified */
-
-static char *parse_address(const char *s, uint16_t *port) {
- assert(s && port);
- if (*s == '[') {
- char *e;
- if (!(e = strchr(s+1, ']')))
- return NULL;
-
- if (e[1] == ':')
- *port = atoi(e+2);
- else if (e[1] != 0)
- return NULL;
-
- return pa_xstrndup(s+1, e-s-1);
- } else {
- char *e;
-
- if (!(e = strrchr(s, ':')))
- return pa_xstrdup(s);
-
- *port = atoi(e+1);
- return pa_xstrndup(s, e-s);
- }
-}
-
struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char*name, uint16_t default_port) {
- const char *p;
struct pa_socket_client *c = NULL;
- enum { KIND_UNIX, KIND_TCP_AUTO, KIND_TCP4, KIND_TCP6 } kind = KIND_TCP_AUTO;
+ struct pa_parsed_address a;
assert(m && name);
- if (*name == '{') {
- char hn[256], *pfx;
- /* The URL starts with a host specification for detecting local connections */
-
- if (!pa_get_host_name(hn, sizeof(hn)))
- return NULL;
-
- pfx = pa_sprintf_malloc("{%s}", hn);
- if (!pa_startswith(name, pfx))
- /* Not local */
- return NULL;
-
- p = name + strlen(pfx);
- } else
- p = name;
-
- if (*p == '/')
- kind = KIND_UNIX;
- else if (pa_startswith(p, "unix:")) {
- kind = KIND_UNIX;
- p += sizeof("unix:")-1;
- } else if (pa_startswith(p, "tcp:") || pa_startswith(p, "tcp4:")) {
- kind = KIND_TCP4;
- p += sizeof("tcp:")-1;
- } else if (pa_startswith(p, "tcp6:")) {
- kind = KIND_TCP6;
- p += sizeof("tcp6:")-1;
- }
+ if (pa_parse_address(name, &a) < 0)
+ return NULL;
- switch (kind) {
- case KIND_UNIX:
- return pa_socket_client_new_unix(m, p);
+ switch (a.type) {
+ case PA_PARSED_ADDRESS_UNIX:
+ c = pa_socket_client_new_unix(m, a.path_or_host);
+ break;
- case KIND_TCP_AUTO: /* Fallthrough */
- case KIND_TCP4:
- case KIND_TCP6: {
- uint16_t port = default_port;
- char *h;
+ case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
+ case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
+ case PA_PARSED_ADDRESS_TCP_AUTO:{
int ret;
struct addrinfo hints, *res;
- if (!(h = parse_address(p, &port)))
- return NULL;
-
memset(&hints, 0, sizeof(hints));
- hints.ai_family = kind == KIND_TCP4 ? AF_INET : (kind == KIND_TCP6 ? AF_INET6 : AF_UNSPEC);
+ hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? AF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? AF_INET6 : AF_UNSPEC);
- ret = getaddrinfo(h, NULL, &hints, &res);
- pa_xfree(h);
+ ret = getaddrinfo(a.path_or_host, NULL, &hints, &res);
if (ret < 0 || !res || !res->ai_addr)
- return NULL;
+ goto finish;
if (res->ai_family == AF_INET) {
if (res->ai_addrlen != sizeof(struct sockaddr_in))
- return NULL;
+ goto finish;
assert(res->ai_addr->sa_family == res->ai_family);
- ((struct sockaddr_in*) res->ai_addr)->sin_port = htons(port);
+ ((struct sockaddr_in*) res->ai_addr)->sin_port = htons(a.port);
} else if (res->ai_family == AF_INET6) {
if (res->ai_addrlen != sizeof(struct sockaddr_in6))
- return NULL;
+ goto finish;
assert(res->ai_addr->sa_family == res->ai_family);
- ((struct sockaddr_in6*) res->ai_addr)->sin6_port = htons(port);
+ ((struct sockaddr_in6*) res->ai_addr)->sin6_port = htons(a.port);
} else
- return NULL;
+ goto finish;
c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
- return c;
}
}
- /* Should never be reached */
- assert(0);
- return NULL;
+finish:
+ pa_xfree(a.path_or_host);
+ return c;
}
diff --git a/polyp/util.c b/polyp/util.c
index ff1aebf3..ee3fa87d 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -880,7 +880,7 @@ int pa_atoi(const char *s, int32_t *ret_i) {
l = strtol(s, &x, 0);
- if (x || *x)
+ if (!x || *x)
return -1;
*ret_i = (int32_t) l;