diff options
Diffstat (limited to 'nx-X11/programs/Xserver/lbx/lbxmain.c')
-rw-r--r-- | nx-X11/programs/Xserver/lbx/lbxmain.c | 1760 |
1 files changed, 1760 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/lbx/lbxmain.c b/nx-X11/programs/Xserver/lbx/lbxmain.c new file mode 100644 index 000000000..9139dfbed --- /dev/null +++ b/nx-X11/programs/Xserver/lbx/lbxmain.c @@ -0,0 +1,1760 @@ +/* $Xorg: lbxmain.c,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */ +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * Copyright 1992 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of NCD. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. NCD. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* $XFree86: xc/programs/Xserver/lbx/lbxmain.c,v 1.12 2001/10/28 03:34:12 tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <sys/types.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xos.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XLBX_SERVER_ +#include <X11/extensions/lbxstr.h> +#include <X11/extensions/lbxdeltastr.h> +#include "lbxserve.h" +#include <X11/extensions/lbximage.h> +#include "lbxsrvopts.h" +#include "lbxtags.h" +#include <X11/Xfuncproto.h> +#include <errno.h> +#ifndef Lynx +#include <sys/uio.h> +#else +#include <uio.h> +#endif +#include <stdio.h> + +#ifndef X_NOT_POSIX +#include <unistd.h> +#endif + +#define CloseLbxClient 0xff + +#define MAXBYTESDIFF 8 + +int LbxWhoAmI = 1; /* + * for lbx zlib library to know who we are + * server = 1 + * proxy = 0 + */ + + +static void LbxResetProc ( ExtensionEntry *extEntry ); +static void LbxFreeClient ( ClientPtr client ); +static void LbxShutdownProxy ( LbxProxyPtr proxy ); +static int DecodeLbxDelta ( ClientPtr client ); + +static LbxProxyPtr proxyList; +unsigned char LbxReqCode; +int LbxEventCode; +static int BadLbxClientCode; +static int uid_seed; + +static int lbxCompressWorkProcCount; + +LbxClientPtr lbxClients[MAXCLIENTS]; + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; +extern int (*LbxInitialVector[3])(ClientPtr); + +#ifdef DEBUG +int lbxDebug = 0; +#endif + + +void +LbxExtensionInit(void) +{ + ExtensionEntry *extEntry; + + lbxCompressWorkProcCount = 0; + proxyList = NULL; + uid_seed = 0; + if ((extEntry = AddExtension(LBXNAME, LbxNumberEvents, LbxNumberErrors, + ProcLbxDispatch, SProcLbxDispatch, + LbxResetProc, StandardMinorOpcode))) + { + LbxReqCode = (unsigned char)extEntry->base; + LbxEventCode = extEntry->eventBase; + BadLbxClientCode = extEntry->errorBase + BadLbxClient; + LbxDixInit(); + + LbxCmapInit (); + DeclareExtensionSecurity(LBXNAME, TRUE); + } +} + +/*ARGSUSED*/ +static void +LbxResetProc (ExtensionEntry *extEntry) +{ + LbxResetTags(); + uid_seed = 0; +} + +void +LbxCloseClient (ClientPtr client) +{ + xLbxCloseEvent closeEvent; + ClientPtr master; + LbxProxyPtr proxy; + LbxClientPtr lbxClient = LbxClient(client); + CARD32 id; + + if (!lbxClient) + return; + id = lbxClient->id; + proxy = lbxClient->proxy; + + DBG (DBG_CLIENT, (stderr, "Close client %d\n", client->index)); + LbxFreeClient (client); + if (!id) + { + isItTimeToYield = TRUE; + CloseDownFileDescriptor (client); + LbxShutdownProxy (proxy); + } + else + { + master = NULL; + if (proxy->lbxClients[0]) + master = LbxProxyClient(proxy); + if (master && !master->clientGone) + { + closeEvent.type = LbxEventCode; + closeEvent.lbxType = LbxCloseEvent; + closeEvent.client = id; + closeEvent.sequenceNumber = master->sequence; + closeEvent.pad1 = closeEvent.pad2 = closeEvent.pad3 = + closeEvent.pad4 = closeEvent.pad5 = closeEvent.pad6 = 0; + if (master->swapped) { + int n; + + swaps(&closeEvent.sequenceNumber, n); + swapl(&closeEvent.client, n); + } + WriteToClient(master, sizeof (closeEvent), (char *)&closeEvent); + LbxForceOutput(proxy); + } + } +} + +static int +LbxReencodeEvent(ClientPtr client, + LbxProxyPtr proxy, + char *buf) +{ + xEvent *ev = (xEvent *)buf; + int n; + lbxMotionCache *motionCache = &proxy->motionCache; + int motionDelta = 0; + Bool swapCache; + xEvent tev, *sev; + + if (ev->u.u.type != MotionNotify) { + if (proxy->dosquishing) + return LbxSquishEvent(buf); + return 0; + } + + /* + * Check if we can generate a motion delta event. + * + * The motion cache contains the last motion event the server sent. + * + * The following are always stored in the cache in the server's + * byte order: + * sequenceNumber, time, rootX, rootY, eventX, eventY + * This is because when determining if we can do a delta, all + * arithmetic must be done using the server's byte order. + * + * The following are stored in the byte order of the latest client + * receiving a motion event (indicated by motionCache->swapped): + * root, event, child, state + * These fields do not need to be stored in the server's byte order + * because we only use the '==' operator on them. + */ + + if (!proxy->motion_allowed_events) { + DBG(DBG_CLIENT, (stderr, "throttling motion event for client %d\n", client->index)); + return sz_xEvent; + } + proxy->motion_allowed_events--; + + motionCache = &proxy->motionCache; + + if (!client->swapped) + { + swapCache = motionCache->swapped; + sev = ev; + } + else + { + swapCache = !motionCache->swapped; + sev = &tev; + cpswaps (ev->u.keyButtonPointer.rootX, + sev->u.keyButtonPointer.rootX); + cpswaps (ev->u.keyButtonPointer.rootY, + sev->u.keyButtonPointer.rootY); + cpswaps (ev->u.keyButtonPointer.eventX, + sev->u.keyButtonPointer.eventX); + cpswaps (ev->u.keyButtonPointer.eventY, + sev->u.keyButtonPointer.eventY); + cpswaps (ev->u.u.sequenceNumber, + sev->u.u.sequenceNumber); + cpswapl (ev->u.keyButtonPointer.time, + sev->u.keyButtonPointer.time); + } + + if (swapCache) + { + swapl (&motionCache->root, n); + swapl (&motionCache->event, n); + swapl (&motionCache->child, n); + swaps (&motionCache->state, n); + + motionCache->swapped = !motionCache->swapped; + } + + motionDelta = 0; + + if (ev->u.u.detail == motionCache->detail && + ev->u.keyButtonPointer.root == motionCache->root && + ev->u.keyButtonPointer.event == motionCache->event && + ev->u.keyButtonPointer.child == motionCache->child && + ev->u.keyButtonPointer.state == motionCache->state && + ev->u.keyButtonPointer.sameScreen == motionCache->sameScreen) { + + int root_delta_x = + sev->u.keyButtonPointer.rootX - motionCache->rootX; + int root_delta_y = + sev->u.keyButtonPointer.rootY - motionCache->rootY; + int event_delta_x = + sev->u.keyButtonPointer.eventX - motionCache->eventX; + int event_delta_y = + sev->u.keyButtonPointer.eventY - motionCache->eventY; + unsigned long sequence_delta = + sev->u.u.sequenceNumber - motionCache->sequenceNumber; + unsigned long time_delta = + sev->u.keyButtonPointer.time - motionCache->time; + + if (root_delta_x == event_delta_x && + event_delta_x >= -128 && event_delta_x < 128 && + root_delta_y == event_delta_y && + event_delta_y >= -128 && event_delta_y < 128) { + + if (sequence_delta == 0 && time_delta < 256) { + + lbxQuickMotionDeltaEvent *mev = + (lbxQuickMotionDeltaEvent *)(buf + sz_xEvent - + sz_lbxQuickMotionDeltaEvent); + + mev->type = LbxEventCode + LbxQuickMotionDeltaEvent; + mev->deltaTime = time_delta; + mev->deltaX = event_delta_x; + mev->deltaY = event_delta_y; + + motionDelta = sz_xEvent - sz_lbxQuickMotionDeltaEvent; + + } else if (sequence_delta < 65536 && time_delta < 65536) { + + lbxMotionDeltaEvent *mev = + (lbxMotionDeltaEvent *)(buf + sz_xEvent - + sz_lbxMotionDeltaEvent); + + mev->type = LbxEventCode; + mev->lbxType = LbxMotionDeltaEvent; + mev->deltaTime = time_delta; + mev->deltaSequence = sequence_delta; + mev->deltaX = event_delta_x; + mev->deltaY = event_delta_y; + + if (LbxProxyClient(proxy)->swapped) + { + swaps (&mev->deltaTime, n); + swaps (&mev->deltaSequence, n); + } + + motionDelta = sz_xEvent - sz_lbxMotionDeltaEvent; + } + } + } + + motionCache->sequenceNumber = sev->u.u.sequenceNumber; + motionCache->time = sev->u.keyButtonPointer.time; + motionCache->rootX = sev->u.keyButtonPointer.rootX; + motionCache->rootY = sev->u.keyButtonPointer.rootY; + motionCache->eventX = sev->u.keyButtonPointer.eventX; + motionCache->eventY = sev->u.keyButtonPointer.eventY; + + if (motionDelta) + return motionDelta; + + ev->u.keyButtonPointer.pad1 = 0; + motionCache->detail = ev->u.u.detail; + motionCache->root = ev->u.keyButtonPointer.root; + motionCache->event = ev->u.keyButtonPointer.event; + motionCache->child = ev->u.keyButtonPointer.child; + motionCache->state = ev->u.keyButtonPointer.state; + motionCache->sameScreen = ev->u.keyButtonPointer.sameScreen; + return 0; +} + +static int +LbxComposeDelta(LbxProxyPtr proxy, + char *reply, + int len, + char *buf) +{ + int diffs; + int cindex; + int n; + xLbxDeltaReq *p = (xLbxDeltaReq *)buf; + + diffs = LBXDeltaMinDiffs(&proxy->outdeltas, (unsigned char *)reply, len, + min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1), + &cindex); + if (diffs < 0) { + LBXAddDeltaOut(&proxy->outdeltas, (unsigned char *)reply, len); + return 0; + } + LBXEncodeDelta(&proxy->outdeltas, (unsigned char *)reply, diffs, cindex, + (unsigned char *)(&buf[sz_xLbxDeltaReq])); + LBXAddDeltaOut(&proxy->outdeltas, (unsigned char *)reply, len); + p->reqType = LbxEventCode; + p->lbxReqType = LbxDeltaEvent; + p->diffs = diffs; + p->cindex = cindex; + len = (sz_xLbxDeltaReq + sz_xLbxDiffItem * diffs + 3) & ~3; + p->length = len >> 2; + if (LbxProxyClient(proxy)->swapped) { + swaps(&p->length, n); + } + return len; +} + +void +LbxReencodeOutput(ClientPtr client, + char *pbuf, + int *pcount, + char *cbuf, + int *ccount) +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + CARD32 len; + int n; + int count = *ccount; + char *obuf = cbuf; + + if (client->clientState != ClientStateRunning) { + if (DELTA_CACHEABLE(&proxy->outdeltas, count) && + (n = LbxComposeDelta(proxy, cbuf, count, proxy->oDeltaBuf))) { + memcpy(obuf, proxy->oDeltaBuf, n); + *ccount -= (count - n); + } + return; + } + if (lbxClient->bytes_remaining) { + if (count < lbxClient->bytes_remaining) { + lbxClient->bytes_remaining -= count; + return; + } + if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply)) { + len = lbxClient->bytes_in_reply - lbxClient->bytes_remaining; + pbuf += (*pcount - len); + memcpy(proxy->replyBuf, pbuf, len); + memcpy(proxy->replyBuf + len, cbuf, lbxClient->bytes_remaining); + n = LbxComposeDelta(proxy, proxy->replyBuf, + lbxClient->bytes_in_reply, proxy->oDeltaBuf); + if (!n) + obuf += lbxClient->bytes_remaining; + else if (n <= len) { + memcpy(pbuf, proxy->oDeltaBuf, n); + *pcount -= (len - n); + *ccount -= lbxClient->bytes_remaining; + } else { + memcpy(pbuf, proxy->oDeltaBuf, len); + memcpy(obuf, proxy->oDeltaBuf + len, n - len); + *ccount -= lbxClient->bytes_remaining - (n - len); + obuf += n - len; + } + } else + obuf += lbxClient->bytes_remaining; + cbuf += lbxClient->bytes_remaining; + count -= lbxClient->bytes_remaining; + lbxClient->bytes_remaining = 0; + } + while (count) { + lbxClient->bytes_in_reply = sz_xEvent; + if (((xGenericReply *)cbuf)->type == X_Reply) { + len = ((xGenericReply *)cbuf)->length; + if (client->swapped) { + swapl(&len, n); + } + lbxClient->bytes_in_reply += (len << 2); + if (LbxProxyClient(proxy)->swapped != client->swapped) { + swapl(&((xGenericReply *)cbuf)->length, n); + } + if (count < lbxClient->bytes_in_reply) { + lbxClient->bytes_remaining = lbxClient->bytes_in_reply - count; + if (obuf != cbuf) + memmove(obuf, cbuf, count); + return; + } + } else if (((xGenericReply *)cbuf)->type > X_Reply && + ((xGenericReply *)cbuf)->type < LASTEvent && + (n = LbxReencodeEvent(client, proxy, cbuf))) { + cbuf += n; + *ccount -= n; + count -= n; + if (n == sz_xEvent) + continue; + lbxClient->bytes_in_reply -= n; + } + if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply) && + (n = LbxComposeDelta(proxy, cbuf, lbxClient->bytes_in_reply, + proxy->oDeltaBuf))) { + memcpy(obuf, proxy->oDeltaBuf, n); + obuf += n; + *ccount -= (lbxClient->bytes_in_reply - n); + } else { + if (obuf != cbuf) + memmove(obuf, cbuf, lbxClient->bytes_in_reply); + obuf += lbxClient->bytes_in_reply; + } + cbuf += lbxClient->bytes_in_reply; + count -= lbxClient->bytes_in_reply; + } +} + +/*ARGSUSED*/ +static void +LbxReplyCallback(CallbackListPtr *pcbl, + pointer nulldata, + pointer calldata) +{ + ReplyInfoRec *pri = (ReplyInfoRec *)calldata; + ClientPtr client = pri->client; + LbxClientPtr lbxClient; + REQUEST(xReq); + + if (!pri->startOfReply || stuff->reqType > 127) + return; + lbxClient = LbxClient(client); + if (lbxClient) + ZeroReplyPadBytes(pri->replyData, stuff->reqType); +} + +/* + * XXX If you think this is moronic, you're in good company, + * but things definitely hang if we don't have this. + */ +/* ARGSUSED */ +static Bool +LbxCheckCompressInput (ClientPtr dummy1, + pointer dummy2) +{ + LbxProxyPtr proxy; + + if (!lbxCompressWorkProcCount) + return TRUE; + + for (proxy = proxyList; proxy; proxy = proxy->next) { + if (proxy->compHandle && + proxy->streamOpts.streamCompInputAvail(proxy->fd)) + AvailableClientInput (LbxProxyClient(proxy)); + } + return FALSE; +} + +static Bool +LbxIsClientBlocked (LbxClientPtr lbxClient) +{ + LbxProxyPtr proxy = lbxClient->proxy; + + return (lbxClient->ignored || + (GrabInProgress && lbxClient->client->index != GrabInProgress && + lbxClient != proxy->lbxClients[0])); +} + +static void +LbxSwitchRecv (LbxProxyPtr proxy, + LbxClientPtr lbxClient) +{ + ClientPtr client; + + proxy->curRecv = lbxClient; + if (!lbxClient || lbxClient->client->clientGone) + { + DBG(DBG_CLIENT, (stderr, "switching to dispose input\n")); + lbxClient = proxy->lbxClients[0]; + if (!lbxClient) + return; + } + client = lbxClient->client; + DBG (DBG_SWITCH, (stderr, "switching input to client %d\n", client->index)); + + SwitchClientInput (client, FALSE); + proxy->curDix = lbxClient; +} + +/* ARGSUSED */ +static Bool +LbxWaitForUnblocked (ClientPtr client, + pointer closure) +{ + LbxClientPtr lbxClient; + LbxProxyPtr proxy; + + if (client->clientGone) + return TRUE; + lbxClient = LbxClient(client); + if (!lbxClient) + return TRUE; + proxy = lbxClient->proxy; + if (LbxIsClientBlocked (lbxClient) || + ((lbxClient != proxy->curDix) && proxy->curDix->reqs_pending && + !LbxIsClientBlocked(proxy->curDix))) + return FALSE; + lbxClient->input_blocked = FALSE; + DBG (DBG_BLOCK, (stderr, "client %d no longer blocked, switching\n", + client->index)); + SwitchClientInput (client, TRUE); + proxy->curDix = lbxClient; + return TRUE; +} + +void +LbxSetForBlock(LbxClientPtr lbxClient) +{ + lbxClient->reqs_pending++; + if (!lbxClient->input_blocked) + { + lbxClient->input_blocked = TRUE; + QueueWorkProc(LbxWaitForUnblocked, lbxClient->client, NULL); + } +} + +/* ARGSUSED */ +static int +LbxWaitForUngrab (ClientPtr client, + pointer closure) +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy; + xLbxListenToAllEvent ungrabEvent; + + if (client->clientGone || !lbxClient) + return TRUE; + if (GrabInProgress) + return FALSE; + proxy = lbxClient->proxy; + proxy->grabClient = 0; + ungrabEvent.type = LbxEventCode; + ungrabEvent.lbxType = LbxListenToAll; + ungrabEvent.pad1 = ungrabEvent.pad2 = ungrabEvent.pad3 = + ungrabEvent.pad4 = ungrabEvent.pad5 = ungrabEvent.pad6 = + ungrabEvent.pad7 = 0; + WriteToClient (client, + sizeof(xLbxListenToAllEvent), (char *)&ungrabEvent); + LbxForceOutput(proxy); + return TRUE; +} + +static void +LbxServerGrab(LbxProxyPtr proxy) +{ + LbxClientPtr grabbingLbxClient; + xLbxListenToOneEvent grabEvent; + + /* + * If the current grabbing client has changed, then we need + * to send a message to update the proxy. + */ + + grabEvent.type = LbxEventCode; + grabEvent.lbxType = LbxListenToOne; + if (!(grabbingLbxClient = lbxClients[GrabInProgress]) || + grabbingLbxClient->proxy != proxy) + grabEvent.client = 0xffffffff; /* client other than a proxy client */ + else + grabEvent.client = grabbingLbxClient->id; + grabEvent.pad1 = grabEvent.pad2 = grabEvent.pad3 = + grabEvent.pad4 = grabEvent.pad5 = grabEvent.pad6 = 0; + if (LbxProxyClient(proxy)->swapped) { + int n; + swapl(&grabEvent.client, n); + } + WriteToClient(LbxProxyClient(proxy), + sizeof(xLbxListenToOneEvent), (char *)&grabEvent); + LbxForceOutput(proxy); + if (!proxy->grabClient) + QueueWorkProc(LbxWaitForUngrab, LbxProxyClient(proxy), NULL); + proxy->grabClient = GrabInProgress; +} + +#define MAJOROP(client) ((xReq *)client->requestBuffer)->reqType +#define MINOROP(client) ((xReq *)client->requestBuffer)->data + +static Bool lbxCacheable[] = { + FALSE, /* LbxQueryVersion 0 */ + FALSE, /* LbxStartProxy 1 */ + TRUE, /* LbxStopProxy 2 */ + FALSE, /* LbxSwitch 3 */ + FALSE, /* LbxNewClient 4 */ + TRUE, /* LbxCloseClient 5 */ + TRUE, /* LbxModifySequence 6 */ + FALSE, /* LbxAllowMotion 7 */ + TRUE, /* LbxIncrementPixel 8 */ + FALSE, /* LbxDelta 9 */ + TRUE, /* LbxGetModifierMapping 10 */ + FALSE, /* nothing 11 */ + TRUE, /* LbxInvalidateTag 12 */ + TRUE, /* LbxPolyPoint 13 */ + TRUE, /* LbxPolyLine 14 */ + TRUE, /* LbxPolySegment 15 */ + TRUE, /* LbxPolyRectangle 16 */ + TRUE, /* LbxPolyArc 17 */ + TRUE, /* LbxFillPoly 18 */ + TRUE, /* LbxPolyFillRectangle 19 */ + TRUE, /* LbxPolyFillArc 20 */ + TRUE, /* LbxGetKeyboardMapping 21 */ + TRUE, /* LbxQueryFont 22 */ + TRUE, /* LbxChangeProperty 23 */ + TRUE, /* LbxGetProperty 24 */ + TRUE, /* LbxTagData 25 */ + TRUE, /* LbxCopyArea 26 */ + TRUE, /* LbxCopyPlane 27 */ + TRUE, /* LbxPolyText8 28 */ + TRUE, /* LbxPolyText16 29 */ + TRUE, /* LbxImageText8 30 */ + TRUE, /* LbxImageText16 31 */ + FALSE, /* LbxQueryExtension 32 */ + TRUE, /* LbxPutImage 33 */ + TRUE, /* LbxGetImage 34 */ + FALSE, /* LbxBeginLargeRequest 35 */ + FALSE, /* LbxLargeRequestData 36 */ + FALSE, /* LbxEndLargeRequest 37 */ + FALSE, /* LbxInternAtoms 38 */ + TRUE, /* LbxGetWinAttrAndGeom 39 */ + TRUE, /* LbxGrabCmap 40 */ + TRUE, /* LbxReleaseCmap 41 */ + TRUE, /* LbxAllocColor 42 */ + TRUE, /* LbxSync 43 */ +}; + +#define NUM(a) (sizeof (a) / sizeof (a[0])) + +static int +LbxReadRequestFromClient (ClientPtr client) +{ + int ret; + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + ClientPtr masterClient = LbxProxyClient(proxy); + Bool isblocked; + Bool cacheable; + + DBG (DBG_READ_REQ, (stderr, "Reading request from client %d\n", client->index)); + + if (GrabInProgress && (proxy->grabClient != GrabInProgress)) + LbxServerGrab(proxy); + isblocked = LbxIsClientBlocked(lbxClient); + + if (lbxClient->reqs_pending && !isblocked) { + ret = StandardReadRequestFromClient(client); + if (ret > 0 && (MAJOROP(client) == LbxReqCode) && + (MINOROP(client) == X_LbxEndLargeRequest)) + ret = PrepareLargeReqBuffer(client); + if (!--lbxClient->reqs_pending && (lbxClient != proxy->curRecv)) + LbxSwitchRecv (proxy, proxy->curRecv); + return ret; + } + while (1) { + ret = StandardReadRequestFromClient(masterClient); + if (ret <= 0) + return ret; + client->requestBuffer = masterClient->requestBuffer; + client->req_len = masterClient->req_len; + cacheable = client->clientState == ClientStateRunning; + if (cacheable && (MAJOROP(client) == LbxReqCode)) { + /* Check to see if this request is delta cached */ + if (MINOROP(client) < NUM(lbxCacheable)) + cacheable = lbxCacheable[MINOROP(client)]; + switch (MINOROP(client)) { + case X_LbxSwitch: + /* Switch is sent by proxy */ + if (masterClient->swapped) + SProcLbxSwitch (client); + else + ProcLbxSwitch (client); + return 0; + case X_LbxDelta: + ret = DecodeLbxDelta (client); + DBG(DBG_DELTA, + (stderr,"delta decompressed msg %d, len = %d\n", + (unsigned)((unsigned char *)client->requestBuffer)[0], + ret)); + break; + case X_LbxEndLargeRequest: + if (!isblocked) + ret = PrepareLargeReqBuffer(client); + break; + } + } + if (cacheable && DELTA_CACHEABLE(&proxy->indeltas, ret)) { + DBG(DBG_DELTA, + (stderr, "caching msg %d, len = %d, index = %d\n", + (unsigned)((unsigned char *)client->requestBuffer)[0], + ret, proxy->indeltas.nextDelta)); + LBXAddDeltaIn(&proxy->indeltas, client->requestBuffer, ret); + } + if (client->swapped != masterClient->swapped) { + char n; + /* put length in client order */ + swaps(&((xReq *)client->requestBuffer)->length, n); + } + if (!isblocked) + return ret; + DBG (DBG_BLOCK, (stderr, "Stashing %d bytes for %d\n", + ret, client->index)); + AppendFakeRequest (client, client->requestBuffer, ret); + LbxSetForBlock(lbxClient); + } +} + +static LbxClientPtr +LbxInitClient (LbxProxyPtr proxy, + ClientPtr client, + CARD32 id) +{ + LbxClientPtr lbxClient; + int i; + + lbxClient = (LbxClientPtr) xalloc (sizeof (LbxClientRec)); + if (!lbxClient) + return NULL; + lbxClient->id = id; + lbxClient->client = client; + lbxClient->proxy = proxy; + lbxClient->ignored = FALSE; + lbxClient->input_blocked = FALSE; + lbxClient->reqs_pending = 0; + lbxClient->bytes_in_reply = 0; + lbxClient->bytes_remaining = 0; + client->readRequest = LbxReadRequestFromClient; + bzero (lbxClient->drawableCache, sizeof (lbxClient->drawableCache)); + bzero (lbxClient->gcontextCache, sizeof (lbxClient->gcontextCache)); + lbxClients[client->index] = lbxClient; + for (i = 0; proxy->lbxClients[i]; i++) + ; + if (i > proxy->maxIndex) + proxy->maxIndex = i; + proxy->lbxClients[i] = lbxClient; + proxy->numClients++; + lbxClient->gfx_buffer = (pointer) NULL; + lbxClient->gb_size = 0; + return lbxClient; +} + +static void +LbxFreeClient (ClientPtr client) +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + int i; + + if (lbxClient != proxy->lbxClients[0]) { + if (lbxClient == proxy->curRecv) + LbxSwitchRecv(proxy, NULL); + else if (lbxClient == proxy->curDix) + LbxSwitchRecv(proxy, proxy->curRecv); + } + + --proxy->numClients; + lbxClients[client->index] = NULL; + for (i = 0; i <= proxy->maxIndex; i++) { + if (proxy->lbxClients[i] == lbxClient) { + proxy->lbxClients[i] = NULL; + break; + } + } + while (proxy->maxIndex >= 0 && !proxy->lbxClients[proxy->maxIndex]) + --proxy->maxIndex; + xfree(lbxClient->gfx_buffer); + client->readRequest = StandardReadRequestFromClient; + xfree (lbxClient); +} + +static void +LbxFreeProxy (LbxProxyPtr proxy) +{ + LbxProxyPtr *p; + + LBXFreeDeltaCache(&proxy->indeltas); + LBXFreeDeltaCache(&proxy->outdeltas); + LbxFreeOsBuffers(proxy); + if (proxy->iDeltaBuf) + xfree(proxy->iDeltaBuf); + if (proxy->replyBuf) + xfree(proxy->replyBuf); + if (proxy->oDeltaBuf) + xfree(proxy->oDeltaBuf); + if (proxy->compHandle) + proxy->streamOpts.streamCompFreeHandle(proxy->compHandle); + if (proxy->bitmapCompMethods) + xfree (proxy->bitmapCompMethods); + if (proxy->pixmapCompMethods) + xfree (proxy->pixmapCompMethods); + if (proxy->pixmapCompDepths) + { + int i; + for (i = 0; i < proxy->numPixmapCompMethods; i++) + xfree (proxy->pixmapCompDepths[i]); + xfree (proxy->pixmapCompDepths); + } + + for (p = &proxyList; *p; p = &(*p)->next) { + if (*p == proxy) { + *p = proxy->next; + break; + } + } + if (!proxyList) + DeleteCallback(&ReplyCallback, LbxReplyCallback, NULL); + + xfree (proxy); +} + +LbxProxyPtr +LbxPidToProxy(int pid) +{ + LbxProxyPtr proxy; + + for (proxy = proxyList; proxy; proxy = proxy->next) { + if (proxy->pid == pid) + return proxy; + } + return NULL; +} + +static void +LbxShutdownProxy (LbxProxyPtr proxy) +{ + int i; + ClientPtr client; + + if (proxy->compHandle) + --lbxCompressWorkProcCount; + while (proxy->grabbedCmaps) + LbxReleaseCmap(proxy->grabbedCmaps, FALSE); + for (i = 0; i <= proxy->maxIndex; i++) + { + if (proxy->lbxClients[i]) + { + client = proxy->lbxClients[i]->client; + if (!client->clientGone) + CloseDownClient (client); + } + } + LbxFlushTags(proxy); + LbxFreeProxy(proxy); +} + + +int +ProcLbxQueryVersion (ClientPtr client) +{ + /* REQUEST(xLbxQueryVersionReq); */ + xLbxQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xLbxQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = LBX_MAJOR_VERSION; + rep.minorVersion = LBX_MINOR_VERSION; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xLbxQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +NextProxyID (void) +{ + LbxProxyPtr proxy; + int id; + + for (id = 1; id < MAX_NUM_PROXIES; id++) { + for (proxy = proxyList; proxy && proxy->pid != id; proxy = proxy->next) + ; + if (!proxy) + return id; + } + return -1; +} + +int +ProcLbxStartProxy (ClientPtr client) +{ + REQUEST(xLbxStartProxyReq); + LbxProxyPtr proxy; + LbxClientPtr lbxClient; + int reqlen; + int replylen; + xLbxStartReply *replybuf; + LbxNegOptsRec negopt; + register int n; + pointer compHandle = NULL; + + REQUEST_AT_LEAST_SIZE(xLbxStartProxyReq); + if (lbxClients[client->index]) + return BadLbxClientCode; + proxy = (LbxProxyPtr) xalloc (sizeof (LbxProxyRec)); + if (!proxy) + return BadAlloc; + bzero(proxy, sizeof (LbxProxyRec)); + proxy->pid = NextProxyID(); + if (proxy->pid < 0) { /* too many proxies */ + xfree(proxy); + return BadAlloc; + } + proxy->uid = ++uid_seed; + if (!proxyList) + AddCallback(&ReplyCallback, LbxReplyCallback, NULL); + + if(!proxyList) + proxyList = proxy; + else{ + proxy->next = proxyList; + proxyList = proxy; + } + + /* + * Don't know exactly how big the reply will be, but it won't be + * bigger than the request + */ + reqlen = client->req_len << 2; + replybuf = (xLbxStartReply *) xalloc(max(reqlen, sz_xLbxStartReply)); + if (!replybuf) { + LbxFreeProxy(proxy); + return BadAlloc; + } + + LbxOptionInit(&negopt); + + replylen = LbxOptionParse(&negopt, + (unsigned char *)&stuff[1], + reqlen - sz_xLbxStartProxyReq, + (unsigned char *)&replybuf->optDataStart); + if (replylen < 0) { + /* + * Didn't understand option format, so we'll just end up + * using the defaults. Set nopts so that the proxy will + * be informed that we rejected the options because of + * decoding problems. + */ + LbxOptionInit(&negopt); + negopt.nopts = 0xff; + replylen = 0; + } + + if (LBXInitDeltaCache(&proxy->indeltas, negopt.proxyDeltaN, + negopt.proxyDeltaMaxLen) < 0 + || + LBXInitDeltaCache(&proxy->outdeltas, negopt.serverDeltaN, + negopt.serverDeltaMaxLen) < 0) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + + n = 0; + if (negopt.proxyDeltaN) + n = negopt.proxyDeltaMaxLen; + if (negopt.serverDeltaN && negopt.serverDeltaMaxLen > n) + n = negopt.serverDeltaMaxLen; + if (n && + (!(proxy->iDeltaBuf = (char *)xalloc (n)) || + !(proxy->replyBuf = (char *)xalloc (n)) || + !(proxy->oDeltaBuf = (char *)xalloc (n)))) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + + MakeClientGrabImpervious(client); /* proxy needs to be grab-proof */ + proxy->fd = ClientConnectionNumber(client); + if (negopt.streamOpts.streamCompInit) { + compHandle = + (*negopt.streamOpts.streamCompInit)(proxy->fd, negopt.streamOpts.streamCompArg); + if (!compHandle) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + } + proxy->ofirst = NULL; + proxy->olast = NULL; + if (!LbxInitClient (proxy, client, 0)) + { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + proxy->dosquishing = negopt.squish; + proxy->numBitmapCompMethods = negopt.numBitmapCompMethods; + proxy->bitmapCompMethods = negopt.bitmapCompMethods; + proxy->numPixmapCompMethods = negopt.numPixmapCompMethods; + proxy->pixmapCompMethods = negopt.pixmapCompMethods; + proxy->pixmapCompDepths = negopt.pixmapCompDepths; + + proxy->streamOpts = negopt.streamOpts; + proxy->useTags = negopt.useTags; + + proxy->grabbedCmaps = NULL; + + /* send reply */ + replybuf->type = X_Reply; + replybuf->nOpts = negopt.nopts; + replybuf->sequenceNumber = client->sequence; + + replylen += sz_xLbxStartReplyHdr; + if (replylen < sz_xLbxStartReply) + replylen = sz_xLbxStartReply; + replybuf->length = (replylen - sz_xLbxStartReply + 3) >> 2; + if (client->swapped) { + swaps(&replybuf->sequenceNumber, n); + swapl(&replybuf->length, n); + } + lbxClient = LbxClient(client); + WriteToClient(client, replylen, (char *)replybuf); + + LbxProxyConnection(client, proxy); + lbxClient = proxy->lbxClients[0]; + proxy->curDix = lbxClient; + proxy->curRecv = lbxClient; + proxy->compHandle = compHandle; + + if (proxy->compHandle && !lbxCompressWorkProcCount++) + QueueWorkProc(LbxCheckCompressInput, NULL, NULL); + + xfree(replybuf); + return Success; +} + +int +ProcLbxStopProxy(ClientPtr client) +{ + /* REQUEST(xLbxStopProxyReq); */ + LbxProxyPtr proxy; + LbxClientPtr lbxClient = LbxClient(client); + + REQUEST_SIZE_MATCH(xLbxStopProxyReq); + + if (!lbxClient) + return BadLbxClientCode; + if (lbxClient->id) + return BadLbxClientCode; + + proxy = lbxClient->proxy; + LbxFreeClient (client); + LbxShutdownProxy (proxy); + return Success; +} + +int +ProcLbxSwitch(ClientPtr client) +{ + REQUEST(xLbxSwitchReq); + LbxProxyPtr proxy = LbxMaybeProxy(client); + LbxClientPtr lbxClient; + int i; + + REQUEST_SIZE_MATCH(xLbxSwitchReq); + if (!proxy) + return BadLbxClientCode; + for (i = 0; i <= proxy->maxIndex; i++) { + lbxClient = proxy->lbxClients[i]; + if (lbxClient && lbxClient->id == stuff->client) { + LbxSwitchRecv (proxy, lbxClient); + return Success; + } + } + LbxSwitchRecv (proxy, NULL); + return BadLbxClientCode; +} + +int +ProcLbxBeginLargeRequest(ClientPtr client) +{ + REQUEST(xLbxBeginLargeRequestReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxBeginLargeRequestReq); + if (!AllocateLargeReqBuffer(client, stuff->largeReqLength << 2)) + return BadAlloc; + return Success; +} + + +int +ProcLbxLargeRequestData(ClientPtr client) +{ + REQUEST(xLbxLargeRequestDataReq); + + client->sequence--; + REQUEST_AT_LEAST_SIZE(xLbxLargeRequestDataReq); + if (!AddToLargeReqBuffer(client, (char *) (stuff + 1), + (client->req_len - 1) << 2)) + return BadAlloc; + return Success; +} + + +int +ProcLbxEndLargeRequest(ClientPtr client) +{ + /* REQUEST(xReq); */ + + client->sequence--; + REQUEST_SIZE_MATCH(xReq); + return BadAlloc; +} + + +int +ProcLbxInternAtoms(ClientPtr client) +{ + REQUEST(xLbxInternAtomsReq); + LbxClientPtr lbxClient = LbxClient(client); + xLbxInternAtomsReply *replyRet; + char *ptr = (char *) stuff + sz_xLbxInternAtomsReq; + Atom *atomsRet; + int replyLen, i; + char lenbuf[2]; + CARD16 len; + char n; + + REQUEST_AT_LEAST_SIZE(xLbxInternAtomsReq); + + if (!lbxClient) + return BadLbxClientCode; + if (lbxClient->id) + return BadLbxClientCode; + + replyLen = sz_xLbxInternAtomsReplyHdr + stuff->num * sizeof (Atom); + if (replyLen < sz_xLbxInternAtomsReply) + replyLen = sz_xLbxInternAtomsReply; + + if (!(replyRet = (xLbxInternAtomsReply *) xalloc (replyLen))) + return BadAlloc; + + atomsRet = (Atom *) ((char *) replyRet + sz_xLbxInternAtomsReplyHdr); + + for (i = 0; i < stuff->num; i++) + { + lenbuf[0] = ptr[0]; + lenbuf[1] = ptr[1]; + len = *((CARD16 *) lenbuf); + ptr += 2; + + if ((atomsRet[i] = MakeAtom (ptr, len, TRUE)) == BAD_RESOURCE) + { + xfree (replyRet); + return BadAlloc; + } + + ptr += len; + } + + if (client->swapped) + for (i = 0; i < stuff->num; i++) + swapl (&atomsRet[i], n); + + replyRet->type = X_Reply; + replyRet->sequenceNumber = client->sequence; + replyRet->length = (replyLen - sz_xLbxInternAtomsReply + 3) >> 2; + + if (client->swapped) { + swaps(&replyRet->sequenceNumber, n); + swapl(&replyRet->length, n); + } + + WriteToClient (client, replyLen, (char *) replyRet); + + xfree (replyRet); + + return Success; +} + + +int +ProcLbxGetWinAttrAndGeom(ClientPtr client) +{ + REQUEST(xLbxGetWinAttrAndGeomReq); + xGetWindowAttributesReply wa; + xGetGeometryReply wg; + xLbxGetWinAttrAndGeomReply reply; + WindowPtr pWin; + int status; + + REQUEST_SIZE_MATCH(xLbxGetWinAttrAndGeomReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + + if ((status = GetGeometry(client, &wg)) != Success) + return status; + + reply.type = X_Reply; + reply.length = (sz_xLbxGetWinAttrAndGeomReply - 32) >> 2; + reply.sequenceNumber = client->sequence; + + reply.backingStore = wa.backingStore; + reply.visualID = wa.visualID; +#if defined(__cplusplus) || defined(c_plusplus) + reply.c_class = wa.c_class; +#else + reply.class = wa.class; +#endif + reply.bitGravity = wa.bitGravity; + reply.winGravity = wa.winGravity; + reply.backingBitPlanes = wa.backingBitPlanes; + reply.backingPixel = wa.backingPixel; + reply.saveUnder = wa.saveUnder; + reply.mapInstalled = wa.mapInstalled; + reply.mapState = wa.mapState; + reply.override = wa.override; + reply.colormap = wa.colormap; + reply.allEventMasks = wa.allEventMasks; + reply.yourEventMask = wa.yourEventMask; + reply.doNotPropagateMask = wa.doNotPropagateMask; + reply.pad1 = 0; + reply.root = wg.root; + reply.x = wg.x; + reply.y = wg.y; + reply.width = wg.width; + reply.height = wg.height; + reply.borderWidth = wg.borderWidth; + reply.depth = wg.depth; + reply.pad2 = 0; + + if (client->swapped) + { + register char n; + + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swapl(&reply.visualID, n); + swaps(&reply.class, n); + swapl(&reply.backingBitPlanes, n); + swapl(&reply.backingPixel, n); + swapl(&reply.colormap, n); + swapl(&reply.allEventMasks, n); + swapl(&reply.yourEventMask, n); + swaps(&reply.doNotPropagateMask, n); + swapl(&reply.root, n); + swaps(&reply.x, n); + swaps(&reply.y, n); + swaps(&reply.width, n); + swaps(&reply.height, n); + swaps(&reply.borderWidth, n); + } + + WriteToClient(client, sizeof(xLbxGetWinAttrAndGeomReply), (char *)&reply); + return(client->noClientException); +} + +int +ProcLbxNewClient(ClientPtr client) +{ + REQUEST(xLbxNewClientReq); + ClientPtr newClient; + LbxProxyPtr proxy = LbxMaybeProxy(client); + CARD32 id; + int len, i; + char *setupbuf; + LbxClientPtr lbxClient; + + REQUEST_AT_LEAST_SIZE(xLbxNewClientReq); + + /* save info before our request disappears */ + id = stuff->client; + if (!proxy || !id) + return BadLbxClientCode; + if (proxy->numClients == MAX_LBX_CLIENTS) + return BadAlloc; + for (i = 1; i <= proxy->maxIndex; i++) { + if (proxy->lbxClients[i] && proxy->lbxClients[i]->id == id) + return BadLbxClientCode; + } + len = (client->req_len << 2) - sizeof(xLbxNewClientReq); + setupbuf = (char *)xalloc (len); + if (!setupbuf) + return BadAlloc; + memcpy (setupbuf, (char *)&stuff[1], len); + + newClient = AllocLbxClientConnection (client, proxy); + if (!newClient) + return BadAlloc; + newClient->requestVector = LbxInitialVector; + lbxClient = LbxInitClient (proxy, newClient, id); + if (!lbxClient) + { + CloseDownClient (newClient); + return BadAlloc; + } + + AppendFakeRequest (newClient, setupbuf, len); + xfree (setupbuf); + LbxSetForBlock(lbxClient); + + DBG (DBG_CLIENT, (stderr, "lbxNewClient X %d\n", newClient->index)); + return Success; +} + +int +ProcLbxEstablishConnection(ClientPtr client) +{ + char *reason = NULL; + char *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + prefix->nbytesAuthProto, + auth_proto, + prefix->nbytesAuthString, + auth_string); + + if (client->clientState == ClientStateCheckingSecurity || + client->clientState == ClientStateAuthenticating) + return (client->noClientException = -1); /* XXX some day */ + return(LbxSendConnSetup(client, reason)); +} + +int +ProcLbxCloseClient (ClientPtr client) +{ + REQUEST(xLbxCloseClientReq); + LbxClientPtr lbxClient = LbxClient(client); + + REQUEST_SIZE_MATCH(xLbxCloseClientReq); + if (!lbxClient || lbxClient->id != stuff->client) + return BadLbxClientCode; + + /* this will cause the client to be closed down back in Dispatch() */ + return(client->noClientException = CloseLbxClient); +} + +int +ProcLbxModifySequence (ClientPtr client) +{ + REQUEST(xLbxModifySequenceReq); + + REQUEST_SIZE_MATCH(xLbxModifySequenceReq); + client->sequence += (stuff->adjust - 1); /* Dispatch() adds 1 */ + return Success; +} + +int +ProcLbxAllowMotion (ClientPtr client) +{ + REQUEST(xLbxAllowMotionReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxAllowMotionReq); + LbxAllowMotion(client, stuff->num); + return Success; +} + + +static int +DecodeLbxDelta (ClientPtr client) +{ + REQUEST(xLbxDeltaReq); + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + int len; + unsigned char *buf; + + /* Note that LBXDecodeDelta decodes and adds current msg to the cache */ + len = LBXDecodeDelta(&proxy->indeltas, + (xLbxDiffItem *)(((char *)stuff) + sz_xLbxDeltaReq), + stuff->diffs, stuff->cindex, &buf); + /* + * Some requests, such as FillPoly, result in the protocol input + * buffer being modified. So we need to copy the request + * into a temporary buffer where a write would be harmless. + * Maybe some day do this copying on a case by case basis, + * since not all requests are guilty of this. + */ + memcpy(proxy->iDeltaBuf, buf, len); + + client->requestBuffer = proxy->iDeltaBuf; + client->req_len = len >> 2; + return len; +} + +int +ProcLbxGetModifierMapping(ClientPtr client) +{ + /* REQUEST(xLbxGetModifierMappingReq); */ + + REQUEST_SIZE_MATCH(xLbxGetModifierMappingReq); + return LbxGetModifierMapping(client); +} + +int +ProcLbxGetKeyboardMapping(ClientPtr client) +{ + /* REQUEST(xLbxGetKeyboardMappingReq); */ + + REQUEST_SIZE_MATCH(xLbxGetKeyboardMappingReq); + return LbxGetKeyboardMapping(client); +} + +int +ProcLbxQueryFont(ClientPtr client) +{ + /* REQUEST(xLbxQueryFontReq); */ + + REQUEST_SIZE_MATCH(xLbxQueryFontReq); + return LbxQueryFont(client); +} + +int +ProcLbxChangeProperty(ClientPtr client) +{ + /* REQUEST(xLbxChangePropertyReq); */ + + REQUEST_SIZE_MATCH(xLbxChangePropertyReq); + return LbxChangeProperty(client); +} + +int +ProcLbxGetProperty(ClientPtr client) +{ + /* REQUEST(xLbxGetPropertyReq); */ + + REQUEST_SIZE_MATCH(xLbxGetPropertyReq); + return LbxGetProperty(client); +} + +int +ProcLbxTagData(ClientPtr client) +{ + REQUEST(xLbxTagDataReq); + + client->sequence--; /* not a counted request */ + REQUEST_AT_LEAST_SIZE(xLbxTagDataReq); + + return LbxTagData(client, stuff->tag, stuff->real_length, + (pointer)&stuff[1]); /* better not give any errors */ +} + +int +ProcLbxInvalidateTag(ClientPtr client) +{ + REQUEST(xLbxInvalidateTagReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxInvalidateTagReq); + return LbxInvalidateTag(client, stuff->tag); +} + +int +ProcLbxPolyPoint(ClientPtr client) +{ + return LbxDecodePoly(client, X_PolyPoint, LbxDecodePoints); +} + +int +ProcLbxPolyLine(ClientPtr client) +{ + return LbxDecodePoly(client, X_PolyLine, LbxDecodePoints); +} + +int +ProcLbxPolySegment(ClientPtr client) +{ + return LbxDecodePoly(client, X_PolySegment, LbxDecodeSegment); +} + +int +ProcLbxPolyRectangle(ClientPtr client) +{ + return LbxDecodePoly(client, X_PolyRectangle, LbxDecodeRectangle); +} + +int +ProcLbxPolyArc(ClientPtr client) +{ + return LbxDecodePoly(client, X_PolyArc, LbxDecodeArc); +} + +int +ProcLbxFillPoly(ClientPtr client) +{ + return LbxDecodeFillPoly(client); +} + +int +ProcLbxPolyFillRectangle(ClientPtr client) +{ + return LbxDecodePoly(client, X_PolyFillRectangle, LbxDecodeRectangle); +} + +int +ProcLbxPolyFillArc(ClientPtr client) +{ + return LbxDecodePoly(client, X_PolyFillArc, LbxDecodeArc); +} + +int +ProcLbxCopyArea(ClientPtr client) +{ + return LbxDecodeCopyArea(client); +} + +int +ProcLbxCopyPlane(ClientPtr client) +{ + return LbxDecodeCopyPlane(client); +} + + +int +ProcLbxPolyText(ClientPtr client) +{ + return LbxDecodePolyText(client); +} + +int +ProcLbxImageText(ClientPtr client) +{ + return LbxDecodeImageText(client); +} + +int +ProcLbxQueryExtension(ClientPtr client) +{ + REQUEST(xLbxQueryExtensionReq); + char *ename; + + REQUEST_AT_LEAST_SIZE(xLbxQueryExtensionReq); + ename = (char *) &stuff[1]; + return LbxQueryExtension(client, ename, stuff->nbytes); +} + +int +ProcLbxPutImage(ClientPtr client) +{ + return LbxDecodePutImage(client); +} + +int +ProcLbxGetImage(ClientPtr client) +{ + return LbxDecodeGetImage(client); +} + + +int +ProcLbxSync(ClientPtr client) +{ + xLbxSyncReply reply; + + client->sequence--; /* not a counted request */ + +#ifdef COLOR_DEBUG + fprintf (stderr, "Got LBX sync, seq = 0x%x\n", client->sequence); +#endif + + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.pad0 = reply.pad1 = reply.pad2 = reply.pad3 = reply.pad4 = + reply.pad5 = reply.pad6 = 0; + + if (client->swapped) + { + register char n; + swaps (&reply.sequenceNumber, n); + } + + WriteToClient (client, sz_xLbxSyncReply, (char *)&reply); + + return (client->noClientException); +} + + +int +ProcLbxDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_LbxQueryVersion: + return ProcLbxQueryVersion(client); + case X_LbxStartProxy: + return ProcLbxStartProxy(client); + case X_LbxStopProxy: + return ProcLbxStopProxy(client); + case X_LbxNewClient: + return ProcLbxNewClient(client); + case X_LbxCloseClient: + return ProcLbxCloseClient(client); + case X_LbxModifySequence: + return ProcLbxModifySequence(client); + case X_LbxAllowMotion: + return ProcLbxAllowMotion(client); + case X_LbxIncrementPixel: + return ProcLbxIncrementPixel(client); + case X_LbxGrabCmap: + return ProcLbxGrabCmap(client); + case X_LbxReleaseCmap: + return ProcLbxReleaseCmap(client); + case X_LbxAllocColor: + return ProcLbxAllocColor(client); + case X_LbxGetModifierMapping: + return ProcLbxGetModifierMapping(client); + case X_LbxGetKeyboardMapping: + return ProcLbxGetKeyboardMapping(client); + case X_LbxInvalidateTag: + return ProcLbxInvalidateTag(client); + case X_LbxPolyPoint: + return ProcLbxPolyPoint (client); + case X_LbxPolyLine: + return ProcLbxPolyLine (client); + case X_LbxPolySegment: + return ProcLbxPolySegment (client); + case X_LbxPolyRectangle: + return ProcLbxPolyRectangle (client); + case X_LbxPolyArc: + return ProcLbxPolyArc (client); + case X_LbxFillPoly: + return ProcLbxFillPoly (client); + case X_LbxPolyFillRectangle: + return ProcLbxPolyFillRectangle (client); + case X_LbxPolyFillArc: + return ProcLbxPolyFillArc (client); + case X_LbxQueryFont: + return ProcLbxQueryFont (client); + case X_LbxChangeProperty: + return ProcLbxChangeProperty (client); + case X_LbxGetProperty: + return ProcLbxGetProperty (client); + case X_LbxTagData: + return ProcLbxTagData (client); + case X_LbxCopyArea: + return ProcLbxCopyArea (client); + case X_LbxCopyPlane: + return ProcLbxCopyPlane (client); + case X_LbxPolyText8: + case X_LbxPolyText16: + return ProcLbxPolyText (client); + case X_LbxImageText8: + case X_LbxImageText16: + return ProcLbxImageText (client); + case X_LbxQueryExtension: + return ProcLbxQueryExtension (client); + case X_LbxPutImage: + return ProcLbxPutImage (client); + case X_LbxGetImage: + return ProcLbxGetImage (client); + case X_LbxInternAtoms: + return ProcLbxInternAtoms(client); + case X_LbxGetWinAttrAndGeom: + return ProcLbxGetWinAttrAndGeom(client); + case X_LbxSync: + return ProcLbxSync(client); + case X_LbxBeginLargeRequest: + return ProcLbxBeginLargeRequest(client); + case X_LbxLargeRequestData: + return ProcLbxLargeRequestData(client); + case X_LbxEndLargeRequest: + return ProcLbxLargeRequestData(client); + default: + return BadRequest; + } +} |