The module argument sets the upper limit for the protocol version that we advertize to the clients. That's useful for working around an incompatibility in the N900. When trying to connect to a newer remote server than 0.9.15 from the N900, the protocol version advertized by the remote server needs to be limited to v15, otherwise the connection fails due to a protocol error. --- src/modules/module-protocol-stub.c | 5 +++-- src/pulsecore/protocol-native.c | 29 ++++++++++++++++++++++------- src/pulsecore/protocol-native.h | 1 + 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 29cb419..2fbef35 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -113,7 +113,7 @@ # define TCPWRAP_SERVICE "pulseaudio-native" # define IPV4_PORT PA_NATIVE_DEFAULT_PORT # define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET -# define MODULE_ARGUMENTS_COMMON "cookie", "auth-cookie", "auth-cookie-enabled", "auth-anonymous", +# define MODULE_ARGUMENTS_COMMON "cookie", "auth-cookie", "auth-cookie-enabled", "auth-anonymous", "protocol-version-limit", # ifdef USE_TCP_SOCKETS # include "module-native-protocol-tcp-symdef.h" @@ -133,7 +133,8 @@ # endif PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION); - PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> " + PA_MODULE_USAGE("protocol-version-limit=<protocol version number> " + "auth-anonymous=<don't check for cookies?> " "auth-cookie=<path to cookie file> " "auth-cookie-enabled=<enable cookie authentification?> " AUTH_USAGE diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index e0a195e..ee78163 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2393,11 +2393,12 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta const void*cookie; pa_tagstruct *reply; pa_bool_t shm_on_remote = FALSE, do_shm; + uint32_t client_protocol_version; pa_native_connection_assert_ref(c); pa_assert(t); - if (pa_tagstruct_getu32(t, &c->version) < 0 || + if (pa_tagstruct_getu32(t, &client_protocol_version) < 0 || pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -2405,7 +2406,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta } /* Minimum supported version */ - if (c->version < 8) { + if (client_protocol_version < 8) { pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION); return; } @@ -2413,12 +2414,14 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta /* Starting with protocol version 13 the MSB of the version tag reflects if shm is available for this pa_native_connection or not. */ - if (c->version >= 13) { - shm_on_remote = !!(c->version & 0x80000000U); - c->version &= 0x7FFFFFFFU; + if (client_protocol_version >= 13) { + shm_on_remote = !!(client_protocol_version & 0x80000000U); + client_protocol_version &= 0x7FFFFFFFU; } - pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION); + c->version = PA_MIN(client_protocol_version, c->options->protocol_version_limit); + + pa_log_debug("Protocol version: remote %u, local %u, effective %u", client_protocol_version, PA_PROTOCOL_VERSION, c->version); pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version); @@ -2503,7 +2506,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta pa_pstream_enable_shm(c->pstream, do_shm); reply = reply_new(tag); - pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0)); + pa_tagstruct_putu32(reply, c->options->protocol_version_limit | (do_shm ? 0x80000000 : 0)); #ifdef HAVE_CREDS { @@ -4901,6 +4904,7 @@ pa_native_options* pa_native_options_new(void) { o = pa_xnew0(pa_native_options, 1); PA_REFCNT_INIT(o); + o->protocol_version_limit = PA_PROTOCOL_VERSION; return o; } @@ -4940,6 +4944,17 @@ 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); + if (pa_modargs_get_value_u32(ma, "protocol-version-limit", &o->protocol_version_limit) < 0) { + pa_log("Failed to parse module argument 'protocol-version-limit'."); + return -1; + } + + if (o->protocol_version_limit < 8 || o->protocol_version_limit > PA_PROTOCOL_VERSION) { + pa_log_warn("Module argument 'protocol-version-limit' is set to %u, which is outside the supported range of 8-%u. " + "Ignoring the module argument.", o->protocol_version_limit, PA_PROTOCOL_VERSION); + o->protocol_version_limit = PA_PROTOCOL_VERSION; + } + 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 9712627..2beb7f1 100644 --- a/src/pulsecore/protocol-native.h +++ b/src/pulsecore/protocol-native.h @@ -47,6 +47,7 @@ typedef struct pa_native_options { char *auth_group; pa_ip_acl *auth_ip_acl; pa_auth_cookie *auth_cookie; + uint32_t protocol_version_limit; } pa_native_options; typedef enum pa_native_hook { -- 1.7.5.3