AC_SUBST(HAVE_GLIB12)
AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1])
+AC_PATH_PROG([M4], [m4 gm4], [no])
+if test "x$M4" = xno ; then
+ AC_MSG_ERROR([m4 missing])
+fi
+
AC_MSG_CHECKING([for tcpwrap library and headers])
LIBWRAP_LIBS=
saved_LIBS="$LIBS"
- X11: support for the X11 synchronization extension
- X11: save auth info in root window
- pass meta info for hearing impaired
-- fall back to getpwnam if $HOME doesn't exist
-- module-match: look in $HOME for table
- limit all resources
-- getaddrinfo
+- check getaddrinfo results
- add LGPL blurb to all concerning files
+- non-fp mixing
+- non-fp resampling
** later ***
- xmlrpc/http
libpstream-util.la \
libpdispatch.la \
libauthkey.la \
+ libauthkey-prop.la \
libprotocol-simple.la \
libprotocol-esound.la \
libprotocol-native.la \
polypaudio_INCLUDES = $(INCLTDL)
polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS)
polypaudio_LDFLAGS= -export-dynamic -dlopen force
-#-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
+# -static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h
libprotocol_simple_la_LDFLAGS = -avoid-version
libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h
libprotocol_native_la_LDFLAGS = -avoid-version
-libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la
+libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la
libtagstruct_la_SOURCES = tagstruct.c tagstruct.h
libtagstruct_la_LDFLAGS = -avoid-version
libauthkey_la_SOURCES = authkey.c authkey.h
libauthkey_la_LDFLAGS = -avoid-version
+libauthkey_prop_la_SOURCES = authkey-prop.c authkey-prop.h
+libauthkey_prop_la_LDFLAGS = -avoid-version
+
libsocket_util_la_SOURCES = socket-util.c socket-util.h
libsocket_util_la_LDFLAGS = -avoid-version
module_tunnel_sink_la_SOURCES = module-tunnel.c
module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS)
module_tunnel_sink_la_LDFLAGS = -module -avoid-version
-module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la
+module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
module_tunnel_source_la_SOURCES = module-tunnel.c
module_tunnel_source_la_LDFLAGS = -module -avoid-version
-module_tunnel_source_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la
+module_tunnel_source_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c
module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version
module_x11_publish_la_SOURCES = module-x11-publish.c
module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
module_x11_publish_la_LDFLAGS = -module -avoid-version
-module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la
+module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la libauthkey.la libauthkey-prop.la
endif
chmod u+s $(DESTDIR)$(bindir)/polypaudio
$(SYMDEF_FILES): module-defs.h.m4
- m4 -Dfname="$@" $< > $@
+ $(M4) -Dfname="$@" $< > $@
--- /dev/null
+/* $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 General Public License as published
+ by the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU 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 <assert.h>
+#include <string.h>
+
+#include "xmalloc.h"
+#include "authkey-prop.h"
+#include "props.h"
+#include "log.h"
+
+struct authkey_data {
+ int ref;
+ size_t length;
+};
+
+int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t len) {
+ struct authkey_data *a;
+ assert(c && name && data && len > 0);
+
+ if (!(a = pa_property_get(c, name)))
+ return -1;
+
+ assert(a->length == len);
+ memcpy(data, a+1, len);
+ return 0;
+}
+
+int pa_authkey_prop_put(struct pa_core *c, const char *name, const void *data, size_t len) {
+ struct authkey_data *a;
+ assert(c && name);
+
+ if (pa_property_get(c, name))
+ return -1;
+
+ a = pa_xmalloc(sizeof(struct authkey_data) + len);
+ a->ref = 1;
+ a->length = len;
+ memcpy(a+1, data, len);
+
+ pa_property_set(c, name, a);
+
+ return 0;
+}
+
+void pa_authkey_prop_ref(struct pa_core *c, const char *name) {
+ struct authkey_data *a;
+ assert(c && name);
+
+ a = pa_property_get(c, name);
+ assert(a && a->ref >= 1);
+
+ a->ref++;
+}
+
+void pa_authkey_prop_unref(struct pa_core *c, const char *name) {
+ struct authkey_data *a;
+ assert(c && name);
+
+ a = pa_property_get(c, name);
+ assert(a && a->ref >= 1);
+
+ if (!(--a->ref)) {
+ pa_property_remove(c, name);
+ pa_xfree(a);
+ }
+}
+
+
--- /dev/null
+#ifndef fooauthkeyprophfoo
+#define fooauthkeyprophfoo
+
+/* $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 General Public License as published
+ by the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU 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 "core.h"
+
+/* Return the data of the specified authorization key property. Doesn't alter the refernce count of the key */
+int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t len);
+
+/* Store data in the specified authorization key property. The initial reference count is set to 1 */
+int pa_authkey_prop_put(struct pa_core *c, const char *name, const void *data, size_t len);
+
+/* Increase the reference count of the specified authorization key */
+void pa_authkey_prop_ref(struct pa_core *c, const char *name);
+
+/* Decrease the reference count of the specified authorization key */
+void pa_authkey_prop_unref(struct pa_core *c, const char *name);
+
+#endif
}
int pa_authkey_load_from_home(const char *fn, void *data, size_t length) {
- char *home;
char path[PATH_MAX];
const char *p;
assert(fn && data && length);
if (fn[0] != '/') {
- if (!(home = getenv("HOME")))
+ char homedir[PATH_MAX];
+ if (!pa_get_home_dir(homedir, sizeof(homedir)))
return -2;
- snprintf(path, sizeof(path), "%s/%s", home, fn);
+ snprintf(path, sizeof(path), "%s/%s", homedir, fn);
p = path;
} else
p = fn;
#endif
#define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table"
-#define DEFAULT_MATCH_TABLE_FILE_USER ".polypaudio/.match.table"
+#define DEFAULT_MATCH_TABLE_FILE_USER ".polypaudio/match.table"
static const char* const valid_modargs[] = {
"table",
#include "authkey.h"
#include "socket-client.h"
#include "socket-util.h"
+#include "authkey-prop.h"
#ifdef TUNNEL_SINK
#include "module-tunnel-sink-symdef.h"
pa_usec_t host_latency;
struct pa_time_event *time_event;
-};
+ int auth_cookie_in_property;
+};
static void close_stuff(struct userdata *u) {
+ assert(u);
+
if (u->pstream) {
pa_pstream_close(u->pstream);
pa_pstream_unref(u->pstream);
m->time_restart(e, &ntv);
}
+static int load_key(struct userdata *u, const char*fn) {
+ assert(u);
+
+ u->auth_cookie_in_property = 0;
+
+ if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) {
+ pa_log(__FILE__": using already loaded auth cookie.\n");
+ pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
+ u->auth_cookie_in_property = 1;
+ return 0;
+ }
+
+ if (!fn)
+ fn = PA_NATIVE_COOKIE_FILE;
+
+ if (pa_authkey_load_from_home(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0)
+ return -1;
+
+ pa_log(__FILE__": loading cookie from disk.\n");
+
+ if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0)
+ u->auth_cookie_in_property = 1;
+
+ return 0;
+}
+
int pa__init(struct pa_core *c, struct pa_module*m) {
struct pa_modargs *ma = NULL;
struct userdata *u = NULL;
u->ctag = 1;
u->device_index = u->channel = PA_INVALID_INDEX;
u->host_latency = 0;
-
- if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), u->auth_cookie, sizeof(u->auth_cookie)) < 0) {
- pa_log(__FILE__": failed to load cookie.\n");
+ u->auth_cookie_in_property = 0;
+ u->time_event = NULL;
+
+ if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
goto fail;
- }
if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) {
pa_log(__FILE__": no server specified.\n");
close_stuff(u);
+ if (u->auth_cookie_in_property)
+ pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME);
+
#ifdef TUNNEL_SINK
pa_xfree(u->sink_name);
#else
#include "log.h"
#include "x11wrap.h"
#include "util.h"
-
+#include "native-common.h"
#include "module-x11-publish-symdef.h"
+#include "authkey-prop.h"
+#include "authkey.h"
PA_MODULE_AUTHOR("Lennart Poettering")
PA_MODULE_DESCRIPTION("X11 Credential Publisher")
"display",
"sink",
"source",
+ "cookie",
NULL
};
struct pa_x11_wrapper *x11_wrapper;
Display *display;
char *id;
+ uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
+ int auth_cookie_in_property;
};
static void set_x11_prop(Display *d, const char *name, const char *data) {
return p;
}
+static int load_key(struct userdata *u, const char*fn) {
+ assert(u);
+
+ u->auth_cookie_in_property = 0;
+
+ if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) {
+ pa_log(__FILE__": using already loaded auth cookie.\n");
+ pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
+ u->auth_cookie_in_property = 1;
+ return 0;
+ }
+
+ if (!fn)
+ fn = PA_NATIVE_COOKIE_FILE;
+
+ if (pa_authkey_load_from_home(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0)
+ return -1;
+
+ pa_log(__FILE__": loading cookie from disk.\n");
+
+ if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0)
+ u->auth_cookie_in_property = 1;
+
+ return 0;
+}
+
int pa__init(struct pa_core *c, struct pa_module*m) {
struct userdata *u;
struct pa_modargs *ma = NULL;
char hn[256], un[128];
- const char *t;
+ char hx[PA_NATIVE_COOKIE_LENGTH*2+1];
+ const char *t;
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log(__FILE__": failed to parse module arguments\n");
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
u->core = c;
u->id = NULL;
+ u->auth_cookie_in_property = 0;
+
+ if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
+ goto fail;
if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL))))
goto fail;
if ((t = pa_modargs_get_value(ma, "sink", NULL)))
set_x11_prop(u->display, "POLYP_SINK", t);
+
+ set_x11_prop(u->display, "POLYP_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx)));
pa_modargs_free(ma);
return 0;
del_x11_prop(u->display, "POLYP_SERVER");
del_x11_prop(u->display, "POLYP_SINK");
del_x11_prop(u->display, "POLYP_SOURCE");
+ del_x11_prop(u->display, "POLYP_COOKIE");
XSync(u->display, False);
}
}
if (u->x11_wrapper)
pa_x11_wrapper_unref(u->x11_wrapper);
+ if (u->auth_cookie_in_property)
+ pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME);
+
pa_xfree(u->id);
pa_xfree(u);
}
if (m->core->disallow_module_loading)
return;
+ pa_log(__FILE__": Unloading \"%s\" (index: #%u).\n", m->name, m->index);
+
m->done(m->core, m);
lt_dlclose(m->dl);
#define PA_NATIVE_DEFAULT_PORT 4713
+#define PA_NATIVE_COOKIE_PROPERTY_NAME "protocol-native-cookie"
+
PA_C_DECL_END
#endif
#include "subscribe.h"
#include "log.h"
#include "autoload.h"
+#include "authkey-prop.h"
struct connection;
struct pa_protocol_native;
struct pa_socket_server *server;
struct pa_idxset *connections;
uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
+ int auth_cookie_in_property;
};
static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk);
/*** module entry points ***/
+static int load_key(struct pa_protocol_native*p, const char*fn) {
+ assert(p);
+
+ p->auth_cookie_in_property = 0;
+
+ if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
+ pa_log(__FILE__": using already loaded auth cookie.\n");
+ pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
+ p->auth_cookie_in_property = 1;
+ return 0;
+ }
+
+ if (!fn)
+ fn = PA_NATIVE_COOKIE_FILE;
+
+ if (pa_authkey_load_from_home(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0)
+ return -1;
+
+ pa_log(__FILE__": loading cookie from disk.\n");
+
+ if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
+ p->auth_cookie_in_property = 1;
+
+ return 0;
+}
+
static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) {
struct pa_protocol_native *p;
int public = 0;
}
p = pa_xmalloc(sizeof(struct pa_protocol_native));
+ p->core = c;
+ p->module = m;
+ p->public = public;
+ p->server = NULL;
- if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), p->auth_cookie, sizeof(p->auth_cookie)) < 0) {
+ if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) {
pa_xfree(p);
return NULL;
}
- p->module = m;
- p->public = public;
- p->server = NULL;
- p->core = c;
p->connections = pa_idxset_new(NULL, NULL);
assert(p->connections);
if (p->server)
pa_socket_server_unref(p->server);
-
+
+ if (p->auth_cookie_in_property)
+ pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
+
pa_xfree(p);
}
ret = pa_socket_low_delay(fd);
on = 1;
+/*
#if defined(SOL_TCP) || defined(IPPROTO_TCP)
#if defined(SOL_TCP)
if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
#endif
ret = -1;
#endif
+*/
#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \
defined(IPPROTO_IP))
return fopen(global, "r");
}
+/* Format the specified data as a hexademical string */
+char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
+ size_t i = 0, j = 0;
+ const char hex[] = "0123456789abcdef";
+ assert(d && s && slength > 0);
+
+ while (i < dlength && j+3 <= slength) {
+ s[j++] = hex[*d >> 4];
+ s[j++] = hex[*d & 0xF];
+
+ d++;
+ i++;
+ }
+
+ s[j < slength ? j : slength] = 0;
+ return s;
+}
FILE *pa_open_config_file(const char *env, const char *global, const char *local, char **result);
+char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength);
+
#endif