include: dix.h: add macros for request handlers and swapping

add some macros for making request handlers easier:

    * REQUEST_HEAD_STRUCT() declares a struct and checks size (assuming
      length field already had been swapped)
    * REQUEST_FIELD_CARD16() swaps a CARD16 (word) if neccessary
    * REQUEST_FIELD_CARD32() swaps a CARD32 (dword) if neccessary

How to use them:

    1. move swapping of lengths field into the SProc*Dispatch() and drop it
       from the individual SProc*()'s
    2. put REQUEST_HEAD_STRUCT() ontop of each Proc*()
    3. add REQUEST_FIELD_*() below, for all fields to be swapped and
       drop their swapping from the SProc*()'s
    4. clean up unnecessary wrappers (SProc*()'s just be just call the
       corresponding Proc*() by now)
    5. let demux SProc just swap length field and call the normal Proc*Dispatch()

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
Enrico Weigelt, metux IT consult 2024-07-02 14:10:00 +02:00
parent 1d9c412683
commit 893f56f6b0

257
dix/request_priv.h Normal file
View File

@ -0,0 +1,257 @@
/* SPDX-License-Identifier: MIT OR X11
*
* Copyright © 2024 Enrico Weigelt, metux IT consult <info@metux.net>
*/
#ifndef _XSERVER_DIX_REQUEST_PRIV_H
#define _XSERVER_DIX_REQUEST_PRIV_H
#include "dix.h"
#include "dixstruct.h"
/*
* byte-swapping macros for request handlers
*
* need a ClientPtr client field to be defined
*
* These could be further optimized by using a macro/inline instead of SwapShorts()
*/
#define CLIENT_STRUCT_CARD16_1(buf, a) \
do { if (client->swapped) { \
cpswaps((buf)->a, (buf)->a); \
} } while (0)
#define CLIENT_STRUCT_CARD16_2(buf, a, b) \
do { if (client->swapped) { \
cpswaps((buf)->a, (buf)->a); \
cpswaps((buf)->b, (buf)->b); \
} } while (0)
#define CLIENT_STRUCT_CARD16_3(buf, a, b, c) \
do { if (client->swapped) { \
cpswaps((buf)->a, (buf)->a); \
cpswaps((buf)->b, (buf)->b); \
cpswaps((buf)->c, (buf)->c); \
} } while (0)
#define CLIENT_STRUCT_CARD16_4(buf, a, b, c, d) \
do { if (client->swapped) { \
cpswaps((buf)->a, (buf)->a); \
cpswaps((buf)->b, (buf)->b); \
cpswaps((buf)->c, (buf)->c); \
cpswaps((buf)->d, (buf)->d); \
} } while (0)
#define CLIENT_STRUCT_CARD16_5(buf, a, b, c, d, e) \
do { if (client->swapped) { \
cpswaps((buf)->a, (buf)->a); \
cpswaps((buf)->b, (buf)->b); \
cpswaps((buf)->c, (buf)->c); \
cpswaps((buf)->d, (buf)->d); \
cpswaps((buf)->e, (buf)->e); \
} } while (0)
#define CLIENT_STRUCT_CARD32_1(buf, a) \
do { if (client->swapped) { \
cpswapl((buf)->a, (buf)->a); \
} } while (0)
#define CLIENT_STRUCT_CARD32_2(buf, a, b) \
do { if (client->swapped) { \
cpswapl((buf)->a, (buf)->a); \
cpswapl((buf)->b, (buf)->b); \
} } while (0)
#define CLIENT_STRUCT_CARD32_3(buf, a, b, c) \
do { if (client->swapped) { \
cpswapl((buf)->a, (buf)->a); \
cpswapl((buf)->b, (buf)->b); \
cpswapl((buf)->c, (buf)->c); \
} } while (0)
#define CLIENT_STRUCT_CARD32_4(buf, a, b, c, d) \
do { if (client->swapped) { \
cpswapl((buf)->a, (buf)->a); \
cpswapl((buf)->b, (buf)->b); \
cpswapl((buf)->c, (buf)->c); \
cpswapl((buf)->d, (buf)->d); \
} } while (0)
#define CLIENT_STRUCT_CARD32_5(buf, a, b, c, d, e) \
do { if (client->swapped) { \
cpswapl((buf)->a, (buf)->a); \
cpswapl((buf)->b, (buf)->b); \
cpswapl((buf)->c, (buf)->c); \
cpswapl((buf)->d, (buf)->d); \
cpswapl((buf)->e, (buf)->e); \
} } while (0)
/*
* macros for request handlers
*
* these are handling request packet checking and swapping of multi-byte
* values, if necessary.
*/
/* declare request struct and check size. length already must have been swapped */
#define REQUEST_HEAD_STRUCT(type) \
REQUEST(type); \
if (stuff == NULL) return (BadLength); \
REQUEST_FIELD_CARD16(length); \
REQUEST_SIZE_MATCH(type);
/* declare request struct and check size. length already must have been swapped */
#define REQUEST_HEAD_STRUCT_32L(type) \
REQUEST(type); \
if (stuff == NULL) return (BadLength); \
REQUEST_FIELD_CARD32(length); \
REQUEST_SIZE_MATCH(type);
/* declare request struct and check size (at least as big). length already must have been swapped */
#define REQUEST_HEAD_AT_LEAST(type) \
REQUEST(type); \
if (stuff == NULL) return (BadLength); \
REQUEST_AT_LEAST_SIZE(type); \
REQUEST_FIELD_CARD16(length);
/* declare request struct, do NOT check size !*/
#define REQUEST_HEAD_NO_CHECK(type) \
REQUEST(type); \
if (stuff == NULL) return (BadLength); \
REQUEST_FIELD_CARD16(length);
/* swap a CARD16 request struct field if necessary */
#define REQUEST_FIELD_CARD16(field) \
do { if (client->swapped) swaps(&stuff->field); } while (0)
/* swap a CARD32 request struct field if necessary */
#define REQUEST_FIELD_CARD32(field) \
do { if (client->swapped) swapl(&stuff->field); } while (0)
/* swap a CARD64 request struct field if necessary */
#define REQUEST_FIELD_CARD64(field) \
do { if (client->swapped) swapll(&stuff->field); } while (0)
/* swap CARD16 rest of request (after the struct) */
#define REQUEST_REST_CARD16() \
do { if (client->swapped) SwapRestS(stuff); } while (0)
/* swap CARD32 rest of request (after the struct) */
#define REQUEST_REST_CARD32() \
do { if (client->swapped) SwapRestL(stuff); } while (0)
/* swap a buffer of CARD16's */
#define REQUEST_BUF_CARD16(buf, count) \
do { if (client->swapped) SwapShorts((short*) buf, count); } while (0)
/* swap a buffer of CARD32's */
#define REQUEST_BUF_CARD32(buf, count) \
do { if (client->swapped) SwapLongs((CARD32*) buf, count); } while (0)
/* swap a CARD16 field (if necessary) in reply struct */
#define REPLY_FIELD_CARD16(field) \
do { if (client->swapped) swaps(&rep.field); } while (0)
/* swap a CARD32 field (if necessary) in reply struct */
#define REPLY_FIELD_CARD32(field) \
do { if (client->swapped) swapl(&rep.field); } while (0)
/* swap a CARD64 field (if necessary) in reply struct */
#define REPLY_FIELD_CARD64(field) \
do { if (client->swapped) swapll(&rep.field); } while (0)
/* swap a buffer of CARD16's */
#define REPLY_BUF_CARD16(buf, count) \
do { if (client->swapped) SwapShorts((short*) buf, count); } while (0)
/* swap a buffer of CARD32's */
#define REPLY_BUF_CARD32(buf, count) \
do { if (client->swapped) SwapLongs((CARD32*) buf, count); } while (0)
/* swap a buffer of CARD64's */
#define REPLY_BUF_CARD64(buf, count) \
do { if (client->swapped) { \
CARD64* ____b = (CARD64*)buf; \
for (int ____i=0; ____i<count; ____i++) { \
swapll(&____b[____i]); } } } while (0)
static inline int ClientReplySend(ClientPtr client, xGenericReply *reply, size_t len) {
reply->type = X_Reply;
reply->sequenceNumber = client->sequence;
if (client->swapped) {
swaps(&(reply->sequenceNumber));
swapl(&(reply->length));
}
WriteToClient(client, len, reply);
return Success;
}
// internal - don't use it anywhere outside this header
static inline int __abovezero(int x) {
return (x > 0 ? x : 0);
}
/* intentionally having this inline, so the compiler has good chance
for optimizations */
static inline int ClientReplySendX(ClientPtr client,
xGenericReply *reply,
size_t len,
const void *data1,
size_t data1_len,
const void *data2,
size_t data2_len
) {
data1_len = __abovezero(data1_len);
data2_len = __abovezero(data1_len);
reply->length = bytes_to_int32(
__abovezero(len + data1_len + data2_len - sizeof(xGenericReply)));
reply->type = X_Reply;
reply->sequenceNumber = client->sequence;
if (client->swapped) {
swaps(&(reply->sequenceNumber));
swapl(&(reply->length));
}
WriteToClient(client, len, reply);
if (data1_len && data1)
WriteToClient(client, data1_len, data1);
if (data2_len && data2)
WriteToClient(client, data2_len, data2);
return Success;
}
#define REPLY_SEND() (ClientReplySend(client, (xGenericReply*)&rep, sizeof(rep)))
/* send a reply (fix up some fields) and return Success */
#define REPLY_SEND_RET_SUCCESS() \
do { return REPLY_SEND(); } while (0)
/* send a reply with extra data - also settings the length field */
#define REPLY_SEND_EXTRA(data1, len1) \
do { return ClientReplySendX(client, (xGenericReply*)&rep, \
sizeof(rep), data1, len1, NULL, 0); \
} while (0)
/* send a reply with extra data - also settings the length field */
#define REPLY_SEND_EXTRA_2(data1, len1, data2, len2) \
do { return ClientReplySendX(client, (xGenericReply*)&rep, \
sizeof(rep), data1, len1, data2, len2); \
} while (0)
/* Declare a SProc*Dispatch function, which swaps the length field
(in order to make size check macros work) and then calls the real
dispatcher. The swapping of payload fields must be done in the
real dispatcher (if necessary) - use REQUEST_FIELD_*() macros there.
*/
#define DECLARE_SWAPPED_DISPATCH(_name,_dispatch) \
static int _X_COLD _name(ClientPtr client) { \
REQUEST(xReq); \
return _dispatch(client); \
}
#define DECLARE_SWAPPED_DISPATCH_EXTERN(_name,_dispatch) \
int _X_COLD _name(ClientPtr client) { \
REQUEST(xReq); \
return _dispatch(client); \
}
#endif /* _XSERVER_DIX_REQUEST_PRIV_H */