Xi: return BadValue on XIQueryVersion if the version is less than first call
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 2c23ef83b0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
This commit is contained in:
parent
93d6ba5b71
commit
ea51e9b287
|
@ -70,27 +70,28 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
if (version_compare(XIVersion.major_version, XIVersion.minor_version,
|
||||
stuff->major_version, stuff->minor_version) > 0) {
|
||||
major = stuff->major_version;
|
||||
minor = stuff->minor_version;
|
||||
pXIClient->major_version = major;
|
||||
pXIClient->minor_version = minor;
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user