[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