From bc97b29447bf5c9932ceccb665fa57dd7f654b36 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 2 Mar 2006 21:56:15 +0000 Subject: Negotiate protocol version between server and client. Will allow smoother protocol modifications in the future. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@621 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 25 +++++++++++++++++++++++++ src/polyp/context.h | 6 ++++++ src/polyp/def.h | 1 + src/polyp/error.c | 1 + src/polyp/internal.h | 1 + src/polyp/version.h.in | 4 ++++ src/polypcore/protocol-native.c | 19 ++++++++++++++++--- 7 files changed, 54 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/polyp/context.c b/src/polyp/context.c index 59079cb0..845e88d9 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -354,6 +354,19 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t switch(c->state) { case PA_CONTEXT_AUTHORIZING: { pa_tagstruct *reply; + + if (pa_tagstruct_getu32(t, &c->version) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + /* Minimum supported version */ + if (c->version < 8) { + pa_context_fail(c, PA_ERR_VERSION); + goto finish; + } + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(reply, c->name); pa_pstream_send_tagstruct(c->pstream, reply); @@ -400,6 +413,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { } t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); + pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); @@ -936,6 +950,17 @@ const char* pa_context_get_server(pa_context *c) { return c->server; } +uint32_t pa_context_get_protocol_version(pa_context *c) { + return PA_PROTOCOL_VERSION; +} + +uint32_t pa_context_get_server_protocol_version(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + return c->version; +} + pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) { pa_tagstruct *t; diff --git a/src/polyp/context.h b/src/polyp/context.h index 73bcb698..89febe92 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -115,6 +115,12 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su /** Return the server name this context is connected to. \since 0.7 */ const char* pa_context_get_server(pa_context *c); +/** Return the protocol version of the library. \since 0.8 */ +uint32_t pa_context_get_protocol_version(pa_context *c); + +/** Return the protocol version of the connected server. \since 0.8 */ +uint32_t pa_context_get_server_protocol_version(pa_context *c); + PA_C_DECL_END #endif diff --git a/src/polyp/def.h b/src/polyp/def.h index 426a0c9b..98420bc0 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -125,6 +125,7 @@ enum { PA_ERR_MODINITFAILED, /**< Module initialization failed */ PA_ERR_BADSTATE, /**< Bad state */ PA_ERR_NODATA, /**< No data */ + PA_ERR_VERSION, /**< Incompatible protocol version \since 0.8 */ PA_ERR_MAX /**< Not really an error but the first invalid error code */ }; diff --git a/src/polyp/error.c b/src/polyp/error.c index eff37cc8..3f3e637f 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -48,6 +48,7 @@ static const char* const errortab[PA_ERR_MAX] = { [PA_ERR_MODINITFAILED] = "Module initalization failed", [PA_ERR_BADSTATE] = "Bad state", [PA_ERR_NODATA] = "No data", + [PA_ERR_VERSION] = "Incompatible protocol version", }; const char*pa_strerror(int error) { diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 1443f7a8..82d8f7ce 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -57,6 +57,7 @@ struct pa_context { PA_LLIST_HEAD(pa_stream, streams); PA_LLIST_HEAD(pa_operation, operations); + uint32_t version; uint32_t ctag; uint32_t csyncid; uint32_t error; diff --git a/src/polyp/version.h.in b/src/polyp/version.h.in index 67b7495b..de7b9c1c 100644 --- a/src/polyp/version.h.in +++ b/src/polyp/version.h.in @@ -44,6 +44,10 @@ const char* pa_get_library_version(void); * PA_API_VERSION undefined. */ #define PA_API_VERSION @PA_API_VERSION@ +/** The current protocol version. Version 8 relates to polypaudio 0.8. + * \since 0.8 */ +#define PA_PROTOCOL_VERSION @PA_PROTOCOL_VERSION@ + PA_C_DECL_END #endif diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 76761b73..68dc6366 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -29,6 +29,8 @@ #include #include +#include + #include #include #include @@ -111,6 +113,7 @@ enum { struct connection { int authorized; + uint32_t version; pa_protocol_native *protocol; pa_client *client; pa_pstream *pstream; @@ -866,14 +869,22 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const void*cookie; + pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || + if (pa_tagstruct_getu32(t, &c->version) < 0 || + pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } + /* Minimum supported version */ + if (c->version < 8) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION); + return; + } + if (!c->authorized) { int success = 0; @@ -915,8 +926,10 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t c->auth_timeout_event = NULL; } } - - pa_pstream_send_simple_ack(c->pstream, tag); + + reply = reply_new(tag); + pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION); + pa_pstream_send_tagstruct(c->pstream, reply); } static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { -- cgit