[PATCH] Xi: return BadValue on XIQueryVersion if the version is less than first call
Jeremy Huddleston
jeremyhu at apple.com
Sun Apr 22 21:13:49 PDT 2012
Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
(for the man page update also)
On Apr 22, 2012, at 8:29 PM, Peter Hutterer <peter.hutterer at who-t.net> wrote:
> Clients that use plugin systems may require multiple calls to
> XIQueryVersion from different plugins. The current error handling requires
> client-side synchronisation of version numbers.
>
> The first call to XIQueryVersion defines the server behaviour. Once cached,
> always return that version number to any clients. Unless a client requests a
> version lower than the first defined one, then a BadValue must be returned
> to be protocol-compatible.
>
> Introduced in 2c23ef83b0e03e163aeeb06133538606886f4e9c
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> Xi/xiqueryversion.c | 41 ++++++-------
> test/xi2/protocol-xiqueryversion.c | 113 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 134 insertions(+), 20 deletions(-)
>
> diff --git a/Xi/xiqueryversion.c b/Xi/xiqueryversion.c
> index fc0ca75..6081c41 100644
> --- a/Xi/xiqueryversion.c
> +++ b/Xi/xiqueryversion.c
> @@ -70,28 +70,29 @@ ProcXIQueryVersion(ClientPtr client)
>
> pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
>
> - if (pXIClient->major_version &&
> - (stuff->major_version != pXIClient->major_version ||
> - stuff->minor_version != pXIClient->minor_version))
> - {
> - client->errorValue = stuff->major_version;
> - return BadValue;
> + if (pXIClient->major_version) {
> + if (version_compare(stuff->major_version, stuff->minor_version,
> + pXIClient->major_version, pXIClient->minor_version) < 0) {
> + client->errorValue = stuff->major_version;
> + return BadValue;
> + }
> + major = pXIClient->major_version;
> + minor = pXIClient->minor_version;
> + } else {
> + if (version_compare(XIVersion.major_version, XIVersion.minor_version,
> + stuff->major_version, stuff->minor_version) > 0) {
> + major = stuff->major_version;
> + minor = stuff->minor_version;
> + }
> + else {
> + major = XIVersion.major_version;
> + minor = XIVersion.minor_version;
> + }
> +
> + pXIClient->major_version = major;
> + pXIClient->minor_version = minor;
> }
>
> -
> - if (version_compare(XIVersion.major_version, XIVersion.minor_version,
> - stuff->major_version, stuff->minor_version) > 0) {
> - major = stuff->major_version;
> - minor = stuff->minor_version;
> - }
> - else {
> - major = XIVersion.major_version;
> - minor = XIVersion.minor_version;
> - }
> -
> - pXIClient->major_version = major;
> - pXIClient->minor_version = minor;
> -
> memset(&rep, 0, sizeof(xXIQueryVersionReply));
> rep.repType = X_Reply;
> rep.RepType = X_XIQueryVersion;
> diff --git a/test/xi2/protocol-xiqueryversion.c b/test/xi2/protocol-xiqueryversion.c
> index 2552307..1347e86 100644
> --- a/test/xi2/protocol-xiqueryversion.c
> +++ b/test/xi2/protocol-xiqueryversion.c
> @@ -54,6 +54,8 @@ struct test_data {
> int minor_client;
> int major_server;
> int minor_server;
> + int major_cached;
> + int minor_cached;
> };
>
> static void
> @@ -82,6 +84,24 @@ reply_XIQueryVersion(ClientPtr client, int len, char *data, void *userdata)
> assert((sver > cver) ? ver == cver : ver == sver);
> }
>
> +static void
> +reply_XIQueryVersion_multiple(ClientPtr client, int len, char *data, void *userdata)
> +{
> + xXIQueryVersionReply *rep = (xXIQueryVersionReply *) data;
> + struct test_data *versions = (struct test_data *) userdata;
> +
> + reply_check_defaults(rep, len, XIQueryVersion);
> + assert(rep->length == 0);
> +
> + if (versions->major_cached == -1) {
> + versions->major_cached = rep->major_version;
> + versions->minor_cached = rep->minor_version;
> + }
> +
> + assert(versions->major_cached == rep->major_version);
> + assert(versions->minor_cached == rep->minor_version);
> +}
> +
> /**
> * Run a single test with server version smaj.smin and client
> * version cmaj.cmin. Verify that return code is equal to 'error'.
> @@ -173,12 +193,105 @@ test_XIQueryVersion(void)
> reply_handler = NULL;
> }
>
> +
> +static void
> +test_XIQueryVersion_multiple(void)
> +{
> + xXIQueryVersionReq request;
> + ClientRec client;
> + struct test_data versions;
> + int rc;
> +
> + request_init(&request, XIQueryVersion);
> + client = init_client(request.length, &request);
> +
> + /* Change the server to support 2.2 */
> + XIVersion.major_version = 2;
> + XIVersion.minor_version = 2;
> +
> + reply_handler = reply_XIQueryVersion_multiple;
> + userdata = (void *) &versions;
> +
> + /* run 1 */
> + versions.major_cached = -1;
> + versions.minor_cached = -1;
> +
> + /* client is lower than server, noncached */
> + request.major_version = 2;
> + request.minor_version = 1;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == Success);
> +
> + /* client is higher than server, cached */
> + request.major_version = 2;
> + request.minor_version = 3;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == Success);
> +
> + /* client is equal, cached */
> + request.major_version = 2;
> + request.minor_version = 2;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == Success);
> +
> + /* client is low than cached */
> + request.major_version = 2;
> + request.minor_version = 0;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == BadValue);
> +
> + /* run 2 */
> + client = init_client(request.length, &request);
> + XIVersion.major_version = 2;
> + XIVersion.minor_version = 2;
> + versions.major_cached = -1;
> + versions.minor_cached = -1;
> +
> + request.major_version = 2;
> + request.minor_version = 2;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == Success);
> +
> + request.major_version = 2;
> + request.minor_version = 3;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == Success);
> +
> + request.major_version = 2;
> + request.minor_version = 1;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == BadValue);
> +
> + /* run 3 */
> + client = init_client(request.length, &request);
> + XIVersion.major_version = 2;
> + XIVersion.minor_version = 2;
> + versions.major_cached = -1;
> + versions.minor_cached = -1;
> +
> + request.major_version = 2;
> + request.minor_version = 3;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == Success);
> +
> + request.major_version = 2;
> + request.minor_version = 2;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == Success);
> +
> + request.major_version = 2;
> + request.minor_version = 1;
> + rc = ProcXIQueryVersion(&client);
> + assert(rc == BadValue);
> +}
> +
> int
> main(int argc, char **argv)
> {
> init_simple();
>
> test_XIQueryVersion();
> + test_XIQueryVersion_multiple();
>
> return 0;
> }
> --
> 1.7.10
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>
More information about the xorg-devel
mailing list