[PATCH 11/12] protocol-native: Enable srbchannel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The srbchannel is enabled if protocol version >= 30 and
SHM is available. There is also a module parameter
srbchannel=false that can be used for disabling the srbchannel.

The setup is done in these steps:
1) Server receives authentication (like today)
2) Server sends enable_srbchannel to client
3) Server sends memblock to client
4) Client receives enable_srbchannel
5) Client receives memblock
6) Client sends enable_srbchannel back to server
7) Client switches over
8) Server receives enable_srbchannel and switches over

Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
 src/modules/module-protocol-stub.c |  6 ++-
 src/pulsecore/protocol-native.c    | 75 ++++++++++++++++++++++++++++++++++++++
 src/pulsecore/protocol-native.h    |  1 +
 3 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 3218a01..118351e 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -120,14 +120,17 @@
 #  endif
 
 #  if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS)
-#    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable",
+#    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable", "srbchannel",
 #    define AUTH_USAGE "auth-group=<system group to allow access> auth-group-enable=<enable auth by UNIX group?> "
+#    define SRB_USAGE "srbchannel=<enable shared ringbuffer communication channel?> "
 #  elif defined(USE_TCP_SOCKETS)
 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
 #    define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
+#    define SRB_USAGE
 #  else
 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
 #    define AUTH_USAGE
+#    define SRB_USAGE
 #    endif
 
   PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION);
@@ -135,6 +138,7 @@
                   "auth-cookie=<path to cookie file> "
                   "auth-cookie-enabled=<enable cookie authentication?> "
                   AUTH_USAGE
+                  SRB_USAGE
                   SOCKET_USAGE);
 #elif defined(USE_PROTOCOL_ESOUND)
 #  include <pulsecore/protocol-esound.h>
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 7262944..589013b 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -181,6 +181,7 @@ struct pa_native_connection {
     uint32_t rrobin_index;
     pa_subscription *subscription;
     pa_time_event *auth_timeout_event;
+    pa_srbchannel *srpending;
 };
 
 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
@@ -294,6 +295,7 @@ static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag,
 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 
 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_ERROR] = NULL,
@@ -397,6 +399,8 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
 
     [PA_COMMAND_SET_PORT_LATENCY_OFFSET] = command_set_port_latency_offset,
 
+    [PA_COMMAND_ENABLE_SRBCHANNEL] = command_enable_srbchannel,
+
     [PA_COMMAND_EXTENSION] = command_extension
 };
 
@@ -1327,6 +1331,9 @@ static void native_connection_unlink(pa_native_connection *c) {
     if (c->options)
         pa_native_options_unref(c->options);
 
+    if (c->srpending)
+        pa_srbchannel_free(c->srpending);
+
     while ((r = pa_idxset_first(c->record_streams, NULL)))
         record_stream_unlink(r);
 
@@ -2578,6 +2585,65 @@ static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
     pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
 }
 
+static void setup_srbchannel(pa_native_connection *c) {
+    pa_srbchannel_template srt;
+    pa_srbchannel *sr;
+    pa_memchunk mc;
+    pa_tagstruct *t;
+    int fdlist[2];
+
+    if (!c->options->srbchannel) {
+        pa_log_debug("Disabling srbchannel, reason: Disabled by module parameter");
+        return;
+    }
+
+    if (c->version < 30) {
+        pa_log_debug("Disabling srbchannel, reason: Protocol too old");
+        return;
+    }
+
+    if (!pa_pstream_get_shm(c->pstream)) {
+        pa_log_debug("Disabling srbchannel, reason: No SHM support");
+        return;
+    }
+
+    if (!c->protocol->core->rw_mempool) {
+        pa_log_debug("Disabling srbchannel, reason: No rw memory pool");
+        return;
+    }
+
+    pa_log_debug("Enabling srbchannel...");
+    sr = pa_srbchannel_new(c->protocol->core->mainloop, c->protocol->core->rw_mempool);
+    pa_srbchannel_export(sr, &srt);
+
+    /* Send enable command to client */
+    t = pa_tagstruct_new(NULL, 0);
+    pa_tagstruct_putu32(t, PA_COMMAND_ENABLE_SRBCHANNEL);
+    pa_tagstruct_putu32(t, (size_t) sr); /* tag */
+    fdlist[0] = srt.readfd;
+    fdlist[1] = srt.writefd;
+    pa_pstream_send_tagstruct_with_fds(c->pstream, t, 2, fdlist);
+
+    /* Send ringbuffer memblock to client */
+    mc.memblock = srt.memblock;
+    mc.index = 0;
+    mc.length = pa_memblock_get_length(srt.memblock);
+    pa_pstream_send_memblock(c->pstream, 0, 0, 0, &mc);
+
+    c->srpending = sr;
+}
+
+static void command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
+
+    if (tag != (uint32_t) (size_t) c->srpending)
+        protocol_error(c);
+
+    pa_log_debug("Client enabled srbchannel.");
+    pa_pstream_set_srbchannel(c->pstream, c->srpending);
+    c->srpending = NULL;
+}
+
 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
     const void*cookie;
@@ -2709,6 +2775,8 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
 #else
     pa_pstream_send_tagstruct(c->pstream, reply);
 #endif
+
+    setup_srbchannel(c);
 }
 
 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
@@ -5017,6 +5085,7 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati
     c->protocol = p;
     c->options = pa_native_options_ref(o);
     c->authorized = false;
+    c->srpending = NULL;
 
     if (o->auth_anonymous) {
         pa_log_info("Client authenticated anonymously.");
@@ -5247,6 +5316,12 @@ int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
     pa_assert(PA_REFCNT_VALUE(o) >= 1);
     pa_assert(ma);
 
+    o->srbchannel = true;
+    if (pa_modargs_get_value_boolean(ma, "srbchannel", &o->srbchannel) < 0) {
+        pa_log("srbchannel= expects a boolean argument.");
+        return -1;
+    }
+
     if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
         pa_log("auth-anonymous= expects a boolean argument.");
         return -1;
diff --git a/src/pulsecore/protocol-native.h b/src/pulsecore/protocol-native.h
index 30b99f9..df30d44 100644
--- a/src/pulsecore/protocol-native.h
+++ b/src/pulsecore/protocol-native.h
@@ -44,6 +44,7 @@ typedef struct pa_native_options {
     pa_module *module;
 
     bool auth_anonymous;
+    bool srbchannel;
     char *auth_group;
     pa_ip_acl *auth_ip_acl;
     pa_auth_cookie *auth_cookie;
-- 
1.9.1



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux