1761 lines
46 KiB
C
1761 lines
46 KiB
C
/* $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;
|
|
}
|
|
}
|