1
/* $Xorg: wire.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
4
Copyright 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of The Open Group shall not be
23
used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from The Open Group.
28
* Copyright 1992 Network Computing Devices
30
* Permission to use, copy, modify, distribute, and sell this software and its
31
* documentation for any purpose is hereby granted without fee, provided that
32
* the above copyright notice appear in all copies and that both that
33
* copyright notice and this permission notice appear in supporting
34
* documentation, and that the name of NCD. not be used in advertising or
35
* publicity pertaining to distribution of the software without specific,
36
* written prior permission. NCD. makes no representations about the
37
* suitability of this software for any purpose. It is provided "as is"
38
* without express or implied warranty.
40
* NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
41
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
42
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
44
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
45
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48
/* $XFree86: xc/programs/lbxproxy/di/wire.c,v 1.14 2002/09/19 13:22:03 tsi Exp $ */
63
#include "proxyopts.h"
70
#include "atomcache.h"
75
#include <X11/ICE/ICElib.h>
77
#include "bigreqstr.h"
81
* The following include for utsname.h is from lib/xtrans
83
#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4)
85
#include <sys/utsname.h> /* uname() */
87
#include <unistd.h> /* gethostname() */
91
extern int delta_out_total;
92
extern int delta_out_attempts;
93
extern int delta_out_hits;
94
extern int delta_in_total;
95
extern int delta_in_attempts;
96
extern int delta_in_hits;
102
#define MAXBYTESDIFF 8
115
static void LbxOnlyListenToOneClient();
116
static void LbxListenToAllClients();
119
* Any request that could be delta compressed comes through here
122
WriteReqToServer(client, len, buf, checkLargeRequest)
126
Bool checkLargeRequest;
128
XServerPtr server = client->server;
129
xLbxDeltaReq *p = (xLbxDeltaReq *) server->tempdeltabuf;
133
Bool written = FALSE;
139
if (DELTA_CACHEABLE(&server->outdeltas, len)) {
142
delta_out_attempts++;
145
if ((diffs = LBXDeltaMinDiffs(&server->outdeltas, (unsigned char *)buf,
146
len, min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1),
153
LBXEncodeDelta(&server->outdeltas, (unsigned char *)buf, diffs,
154
cindex, &server->tempdeltabuf[sz_xLbxDeltaReq]);
155
p->reqType = server->lbxReq;
156
p->lbxReqType = X_LbxDelta;
159
newlen = sz_xLbxDeltaReq + sz_xLbxDiffItem * diffs;
160
p->length = (newlen + 3) >> 2;
161
/* Don't byte swap -- lengths are always in proxy order */
162
WriteToServer(client, newlen, (char *) p, TRUE, checkLargeRequest);
165
LBXAddDeltaOut(&server->outdeltas, (unsigned char *)buf, len);
169
if (len > (0xffff << 2)) {
171
bigreq.reqType = ((xReq *)buf)->reqType;
172
bigreq.data = ((xReq *)buf)->data;
174
bigreq.length = (len + sizeof(xBigReq) - sizeof(xReq)) >> 2;
175
WriteToServer(client, sizeof(xBigReq), (char *)&bigreq,
176
TRUE, checkLargeRequest);
177
WriteToServer(client, len - sizeof(xReq), buf + sizeof(xReq),
178
FALSE, checkLargeRequest);
182
WriteToServer(client, len, buf, TRUE, checkLargeRequest);
187
_write_to_server(client, compressed, len, buf, checkLarge, startOfRequest)
195
XServerPtr server = client->server;
198
if (server->serverClient->clientGone)
201
if (checkLarge && client != clients[0] && nClients > 1 &&
202
((client != server->prev_exec) || numLargeRequestsInQueue)) {
204
* Check if this is a large request only if there is more than
205
* one client and a different client was the last to execute or
206
* there are already large requests queued.
208
* If it is a large request, and there is room in the large request
209
* queue, add it to the queue. lbxproxy will send the large request
210
* in chunks, preventing this client from hogging the wire.
212
* By checking that the previous client was someone else,
213
* we hope that we can prevent splitting a large request
214
* when the other clients appear to be idle (based on their past
218
if (startOfRequest &&
219
(!(reqSize = (((xReq *) buf)->length) << 2) ||
220
reqSize >= LBX_LARGE_REQUEST_MIN_SIZE) &&
221
numLargeRequestsInQueue < LARGE_REQUEST_QUEUE_LEN) {
222
LbxLargeRequestRec *largeRequest;
225
reqSize = ((xBigReq *)buf)->length << 2;
226
largeRequest = (LbxLargeRequestRec *)
227
xalloc (sizeof (LbxLargeRequestRec) + reqSize);
230
* Add this large request to the queue
233
largeRequest->client = client;
234
largeRequest->compressed = compressed;
235
largeRequest->buf = (char *) largeRequest +
236
sizeof (LbxLargeRequestRec);
237
memcpy (largeRequest->buf, buf, len);
238
largeRequest->totalBytes = reqSize;
239
largeRequest->bytesRead = len;
240
largeRequest->bytesWritten = 0;
241
client->largeRequest = largeRequest;
243
largeRequestQueue[numLargeRequestsInQueue++] = largeRequest;
246
* Once we have the whole large request, we want to disable
247
* input from this client - we don't want to read new requests
248
* until we are done sending the whole large request.
252
IgnoreClient(client);
255
} else if (client->largeRequest) {
258
* Append to the large request
261
char *dst = client->largeRequest->buf +
262
client->largeRequest->bytesRead;
263
memcpy (dst, buf, len);
264
client->largeRequest->bytesRead += len;
267
* Once we have the whole large request, we want to disable
268
* input from this client - we don't want to read new requests
269
* until we are done sending the whole large request.
272
if (client->largeRequest->bytesRead ==
273
client->largeRequest->totalBytes)
274
IgnoreClient(client);
280
if (server->send != client) {
283
DBG(DBG_SWITCH, (stderr, "switch downstream to %d\n", client->index));
284
s.reqType = server->lbxReq;
285
s.lbxReqType = X_LbxSwitch;
287
s.client = client->index;
288
WriteToClient(server->serverClient, sizeof(s), &s);
289
server->send = client;
291
DBG(DBG_IO, (stderr, "downstream %d len %d\n", client->index, len));
292
if (compressed || !server->compHandle)
293
WriteToClient(server->serverClient, len, buf);
295
UncompressWriteToClient(server->serverClient, len, buf);
299
WriteToServer(client, len, buf, startOfRequest, checkLargeRequest)
304
Bool checkLargeRequest;
306
_write_to_server(client, TRUE, len, buf, checkLargeRequest, startOfRequest);
310
WriteToServerUncompressed(client, len, buf, startOfRequest)
316
_write_to_server(client, FALSE, len, buf, TRUE, startOfRequest);
319
/* all these requests may need to be swapped back to the order of
320
* the client they're being executed for
323
NewClient(client, setuplen)
328
XServerPtr server = client->server;
330
DBG(DBG_CLIENT, (stderr, "new client %d\n", client->index));
331
n.reqType = server->lbxReq;
332
n.lbxReqType = X_LbxNewClient;
333
n.length = 2 + (setuplen >> 2);
334
n.client = client->index;
335
WriteToServer(server->serverClient, sizeof(n), (char *) &n, TRUE, FALSE);
336
++server->serverClient->sequence;
344
xLbxCloseClientReq n;
345
XServerPtr server = client->server;
350
if (client->server->serverClient == client)
352
if (client->server->serverClient->clientGone)
354
DBG(DBG_CLIENT, (stderr, "closing down client %d\n", client->index));
355
if (client->closeDownMode != DestroyAll) {
356
n.reqType = server->lbxReq;
357
n.lbxReqType = X_LbxCloseClient;
359
n.client = client->index;
360
if (client->swapped) {
363
WriteReqToServer(client, sizeof(n), (char *) &n, TRUE);
368
ModifySequence(client, num)
372
xLbxModifySequenceReq req;
373
XServerPtr server = client->server;
375
if (client->server->serverClient == client)
377
req.reqType = server->lbxReq;
378
req.lbxReqType = X_LbxModifySequence;
381
if (client->swapped) {
382
SwapModifySequence(&req);
384
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
388
AllowMotion(client, num)
392
client->server->motion_allowed += num;
396
SendIncrementPixel(client, cmap, pixel)
401
xLbxIncrementPixelReq req;
402
XServerPtr server = client->server;
404
if (client->server->serverClient == client)
406
req.reqType = server->lbxReq;
407
req.lbxReqType = X_LbxIncrementPixel;
411
if (client->swapped) {
412
SwapIncrementPixel(&req);
414
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
418
#ifdef NeedFunctionPrototypes
427
SendAllocColor(client, cmap, pixel, red, green, blue)
431
CARD16 red, green, blue;
434
xLbxAllocColorReq req;
436
req.reqType = client->server->lbxReq;
437
req.lbxReqType = X_LbxAllocColor;
438
req.length = sz_xLbxAllocColorReq >> 2;
447
SwapAllocColor (&req);
449
WriteReqToServer (client, sizeof(req), (char *) &req, TRUE);
453
SendGetModifierMapping(client)
456
xLbxGetModifierMappingReq req;
457
XServerPtr server = client->server;
459
if (client->server->serverClient == client)
462
req.reqType = server->lbxReq;
463
req.lbxReqType = X_LbxGetModifierMapping;
465
if (client->swapped) {
466
SwapGetModifierMapping(&req);
468
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
472
SendGetKeyboardMapping(client)
475
xLbxGetKeyboardMappingReq req;
476
XServerPtr server = client->server;
478
if (client->server->serverClient == client)
482
* always ask for entire thing so tag always works, and pass on requested
485
req.reqType = server->lbxReq;
486
req.lbxReqType = X_LbxGetKeyboardMapping;
488
req.firstKeyCode = LBXMinKeyCode(client);
489
req.count = LBXMaxKeyCode(client) - LBXMinKeyCode(client) + 1;
491
if (client->swapped) {
492
SwapGetKeyboardMapping(&req);
494
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
498
SendQueryFont(client, fid)
502
xLbxQueryFontReq req;
503
XServerPtr server = client->server;
505
if (client->server->serverClient == client)
508
req.reqType = server->lbxReq;
509
req.lbxReqType = X_LbxQueryFont;
512
if (client->swapped) {
515
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
519
SendChangeProperty(client, win, prop, type, format, mode, num)
528
xLbxChangePropertyReq req;
529
XServerPtr server = client->server;
531
if (client->server->serverClient == client)
534
req.reqType = server->lbxReq;
535
req.lbxReqType = X_LbxChangeProperty;
543
req.pad[0] = req.pad[1] = 0;
544
if (client->swapped) {
545
SwapChangeProperty(&req);
547
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
551
SendGetProperty(client, win, prop, type, delete, off, len)
560
xLbxGetPropertyReq req;
561
XServerPtr server = client->server;
563
if (client->server->serverClient == client)
566
req.reqType = server->lbxReq;
567
req.lbxReqType = X_LbxGetProperty;
573
req.longOffset = off;
574
req.longLength = len;
575
req.pad[0] = req.pad[1] = req.pad[2] = 0;
576
if (client->swapped) {
577
SwapGetProperty(&req);
579
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
583
SendInvalidateTag(client, tag)
587
xLbxInvalidateTagReq req;
590
if (!servers[0]) /* proxy resetting */
593
server = client->server;
595
req.reqType = server->lbxReq;
596
req.lbxReqType = X_LbxInvalidateTag;
599
/* need tag type ? */
600
if (client->swapped) {
601
SwapInvalidateTag(&req);
603
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
607
SendTagData(client, tag, len, data)
618
server = client->server;
620
req_len = 3 + ((len + 3) >> 2);
621
if (DELTA_CACHEABLE(&server->outdeltas, req_len << 2)) {
622
reqp = (xLbxTagDataReq *) xalloc(req_len << 2);
623
memcpy((pointer) (reqp + 1), data, len);
627
reqp->reqType = server->lbxReq;
628
reqp->lbxReqType = X_LbxTagData;
629
reqp->length = req_len;
630
reqp->real_length = len;
632
/* need tag type ? */
634
WriteToServer(server->serverClient,
635
sizeof(req), (char *) &req, TRUE, FALSE);
637
WriteToServer(server->serverClient,
638
len, (char *) data, FALSE, FALSE);
640
WriteReqToServer(server->serverClient,
641
req_len << 2, (char *) reqp, FALSE);
647
SendGetImage(client, drawable, x, y, width, height, planeMask, format)
654
unsigned long planeMask;
658
XServerPtr server = client->server;
660
if (client->server->serverClient == client)
663
req.reqType = server->lbxReq;
664
req.lbxReqType = X_LbxGetImage;
666
req.drawable = drawable;
671
req.planeMask = planeMask;
676
if (client->swapped) {
679
WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
683
SendInternAtoms (server)
686
xLbxInternAtomsReq *req;
691
reqSize = sz_xLbxInternAtomsReq;
693
for (i = 0; i < server->atom_control_count; i++) {
694
if (server->atom_control[i].flags & AtomPreInternFlag) {
695
reqSize += (2 + server->atom_control[i].len);
702
if (!(req = (xLbxInternAtomsReq *) xalloc (reqSize)))
705
req->reqType = server->lbxReq;
706
req->lbxReqType = X_LbxInternAtoms;
707
req->length = (reqSize + 3) >> 2;
710
ptr = (char *) req + sz_xLbxInternAtomsReq;
712
for (i = 0; i < server->atom_control_count; i++)
714
if (server->atom_control[i].flags & AtomPreInternFlag) {
715
*((CARD16 *) lenbuf) = server->atom_control[i].len;
720
server->atom_control[i].name,
721
server->atom_control[i].len);
722
ptr += server->atom_control[i].len;
726
WriteToClient(server->serverClient, reqSize, (char *) req);
734
InternAtomsReply (server, rep)
736
xLbxInternAtomsReply *rep;
738
Atom *atoms = (Atom *) ((char *) rep + sz_xLbxInternAtomsReplyHdr);
741
for (i = 0; i < server->atom_control_count; i++) {
742
if (server->atom_control[i].flags & AtomPreInternFlag)
743
(void) LbxMakeAtom (server,
744
server->atom_control[i].name,
745
server->atom_control[i].len,
749
SendInitLBXPackets(server);
752
* Now the proxy is ready to accept connections from clients.
755
(void) ListenWellKnownSockets ();
759
static unsigned long pendingServerReplySequence;
760
static void (*serverReplyFunc) ();
763
ServerReply(server, rep)
767
if (serverReplyFunc &&
768
rep->generic.sequenceNumber == pendingServerReplySequence) {
770
* We got the reply we were waiting from the server
773
(*serverReplyFunc) (server, rep);
776
* ExpectServerReply() might have been called within the server
777
* reply func just processed.
780
if (rep->generic.sequenceNumber == pendingServerReplySequence)
786
ExpectServerReply(server, func)
790
pendingServerReplySequence = server->serverClient->sequence;
791
serverReplyFunc = func;
794
extern int (*ServerVector[]) ();
797
ServerRequestLength(req, sc, gotnow, partp)
803
XServerPtr server = servers[sc->lbxIndex];
804
ClientPtr client = server->recv;
806
xConnSetupPrefix *pre;
809
req = (xReq *) sc->requestBuffer;
810
if (gotnow < sizeof(xReq)) {
814
if (req->reqType == server->lbxEvent && req->data == LbxDeltaEvent) {
816
return req->length << 2;
818
if (req->reqType == server->lbxEvent && req->data == LbxSwitchEvent) {
820
return sz_xLbxSwitchEvent;
822
if (req->reqType == server->lbxEvent + LbxQuickMotionDeltaEvent) {
824
return sz_lbxQuickMotionDeltaEvent;
826
if (req->reqType == server->lbxEvent && req->data == LbxMotionDeltaEvent) {
828
return sz_lbxMotionDeltaEvent;
830
if (client->awaitingSetup) {
835
pre = (xConnSetupPrefix *) req;
837
return 8 + (pre->length << 2);
844
rep = (xReply *) req;
845
if (rep->generic.type != X_Reply) {
846
return EventLength((xEvent *)rep, server->lbxNegOpt.squish);
848
return sz_xReply + (rep->generic.length << 2);
852
ServerProcStandardEvent(sc)
856
XServerPtr server = servers[sc->lbxIndex];
857
ClientPtr client = server->recv;
860
Bool cacheable = (server->initialized) ? TRUE : FALSE;
862
rep = (xReply *) sc->requestBuffer;
864
/* need to calculate length up from for Delta cache */
865
len = RequestLength(rep, sc, 8, &part);
871
if (rep->generic.type == server->lbxEvent &&
872
rep->generic.data1 == LbxDeltaEvent) {
873
xLbxDeltaReq *delta = (xLbxDeltaReq *) rep;
880
/* Note that LBXDecodeDelta decodes and adds current msg to the cache */
881
len = LBXDecodeDelta(&server->indeltas,
882
(xLbxDiffItem *)((char *) rep + sz_xLbxDeltaReq),
883
delta->diffs, delta->cindex,
884
(unsigned char **)&rep);
886
/* Make local copy in case someone writes to the request buffer */
887
memcpy(server->tempdeltabuf, (char *) rep, len);
888
rep = (xReply *) server->tempdeltabuf;
893
/* stick in delta buffer before LBX code modified things */
894
if (cacheable && DELTA_CACHEABLE(&server->indeltas, len)) {
900
LBXAddDeltaIn(&server->indeltas, (unsigned char *) rep, len);
902
if (rep->generic.type == server->lbxEvent &&
903
rep->generic.data1 != LbxMotionDeltaEvent) {
904
switch (rep->generic.data1) {
906
DBG(DBG_SWITCH, (stderr, "switch upstream to %d\n",
907
((xLbxSwitchEvent *)rep)->client));
908
client = clients[((xLbxSwitchEvent *)rep)->client];
909
server->recv = client;
910
(void) CheckPendingClientInput(sc);
913
DBG(DBG_CLIENT, (stderr, "close client %d\n",
914
((xLbxCloseEvent *)rep)->client));
915
client = clients[((xLbxCloseEvent *)rep)->client];
916
client->closeDownMode = DestroyAll;
917
CloseDownClient(client);
919
case LbxInvalidateTagEvent:
920
DBG(DBG_CLIENT, (stderr, "invalidate tag %d type %d\n",
921
((xLbxInvalidateTagEvent *)rep)->tag,
922
((xLbxInvalidateTagEvent *)rep)->tagType));
924
((xLbxInvalidateTagEvent *)rep)->tag,
925
((xLbxInvalidateTagEvent *)rep)->tagType);
927
case LbxSendTagDataEvent:
928
DBG(DBG_CLIENT, (stderr, "send tag data %d type %d\n",
929
((xLbxSendTagDataEvent *)rep)->tag,
930
((xLbxSendTagDataEvent *)rep)->tagType));
932
((xLbxSendTagDataEvent *)rep)->tag,
933
((xLbxSendTagDataEvent *)rep)->tagType);
936
DBG(DBG_CLIENT, (stderr, "listen to one client %d\n",
937
((xLbxListenToOneEvent *)rep)->client));
938
if (((xLbxListenToOneEvent *)rep)->client == 0xffffffff)
939
LbxOnlyListenToOneClient(server->serverClient);
941
LbxOnlyListenToOneClient(clients[((xLbxListenToOneEvent *)rep)->client]);
944
DBG(DBG_CLIENT, (stderr, "listen to all clients\n"));
945
LbxListenToAllClients(server);
947
case LbxReleaseCmapEvent:
949
Colormap cmap = ((xLbxReleaseCmapEvent *)rep)->colormap;
952
pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
954
fprintf (stderr, "\nGot LbxReleaseCmapEvent, cmap = 0x%x\n\n", cmap);
956
if (pmap && pmap->grab_status == CMAP_GRABBED)
957
ReleaseCmap (client, pmap);
960
case LbxFreeCellsEvent:
962
Colormap cmap = ((xLbxFreeCellsEvent *)rep)->colormap;
963
Pixel start = ((xLbxFreeCellsEvent *)rep)->pixelStart;
964
Pixel end = ((xLbxFreeCellsEvent *)rep)->pixelEnd;
967
pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
969
fprintf (stderr, "\nGot LbxFreeCellsEvent, cmap = 0x%x, ", cmap);
970
fprintf (stderr, "startPixel = %d, endPixel = %d\n\n",
973
if (pmap && pmap->grab_status == CMAP_GRABBED)
974
GotServerFreeCellsEvent (pmap, start, end);
978
} else if ((rep->generic.type == server->lbxEvent &&
979
rep->generic.data1 == LbxMotionDeltaEvent) ||
980
(rep->generic.type == server->lbxEvent + LbxQuickMotionDeltaEvent))
982
lbxMotionCache *motionCache = &server->motionCache;
985
* We use the motion delta event to generate a real MotionNotify event.
987
* The motion cache contains the last motion event we got from
990
* The following are always stored in the cache in the proxy's
992
* sequenceNumber, time, rootX, rootY, eventX, eventY
993
* This is because when constructing the MotionNotify event using
994
* the delta event, we must do arithmetic in the proxy's byte order.
996
* The following are stored in the byte order of the latest client
997
* receiving a motion event (indicated by motionCache->swapped):
998
* root, event, child, state
999
* The assumption is that a client will receive a series of motion
1000
* events, and we don't want to unnecessarily swap these fields.
1001
* If the next motion event goes to a client with a byte order
1002
* different from the previous client, we will have to swap these
1006
AllowMotion(client, 1);
1008
if (rep->generic.type == server->lbxEvent)
1010
lbxMotionDeltaEvent *mev = (lbxMotionDeltaEvent *) rep;
1012
motionCache->sequenceNumber += mev->deltaSequence;
1013
motionCache->time += mev->deltaTime;
1014
motionCache->rootX += mev->deltaX;
1015
motionCache->rootY += mev->deltaY;
1016
motionCache->eventX += mev->deltaX;
1017
motionCache->eventY += mev->deltaY;
1021
lbxQuickMotionDeltaEvent *qmev = (lbxQuickMotionDeltaEvent *) rep;
1023
motionCache->time += qmev->deltaTime;
1024
motionCache->rootX += qmev->deltaX;
1025
motionCache->rootY += qmev->deltaY;
1026
motionCache->eventX += qmev->deltaX;
1027
motionCache->eventY += qmev->deltaY;
1030
if (!client->clientGone) {
1034
if (motionCache->swapped != client->swapped)
1036
swapl (&motionCache->root, n);
1037
swapl (&motionCache->event, n);
1038
swapl (&motionCache->child, n);
1039
swaps (&motionCache->state, n);
1040
motionCache->swapped = client->swapped;
1043
ev.u.u.type = MotionNotify;
1044
ev.u.u.detail = motionCache->detail;
1045
ev.u.u.sequenceNumber = motionCache->sequenceNumber;
1046
ev.u.keyButtonPointer.time = motionCache->time;
1047
ev.u.keyButtonPointer.rootX = motionCache->rootX;
1048
ev.u.keyButtonPointer.rootY = motionCache->rootY;
1049
ev.u.keyButtonPointer.eventX = motionCache->eventX;
1050
ev.u.keyButtonPointer.eventY = motionCache->eventY;
1051
ev.u.keyButtonPointer.root = motionCache->root;
1052
ev.u.keyButtonPointer.event = motionCache->event;
1053
ev.u.keyButtonPointer.child = motionCache->child;
1054
ev.u.keyButtonPointer.state = motionCache->state;
1055
ev.u.keyButtonPointer.sameScreen = motionCache->sameScreen;
1057
if (client->swapped) {
1058
swaps (&ev.u.u.sequenceNumber, n);
1059
swapl (&ev.u.keyButtonPointer.time, n);
1060
swaps (&ev.u.keyButtonPointer.rootX, n);
1061
swaps (&ev.u.keyButtonPointer.rootY, n);
1062
swaps (&ev.u.keyButtonPointer.eventX, n);
1063
swaps (&ev.u.keyButtonPointer.eventY, n);
1069
DoLBXReply (client, (char *) &ev, sz_xEvent);
1073
len = RequestLength(rep, sc, 8, &part);
1074
DBG(DBG_IO, (stderr, "upstream %d len %d\n", client->index, len));
1075
if (client->index == 0) {
1076
ServerReply(server, rep);
1082
if (!client->awaitingSetup && UnsquishEvent(rep, &ev, &len))
1087
if (rep->generic.type == MotionNotify) {
1088
xEvent *mev = (xEvent *) rp;
1089
lbxMotionCache *motionCache = &server->motionCache;
1091
AllowMotion(client, 1);
1092
motionCache->swapped = client->swapped;
1093
motionCache->detail = mev->u.u.detail;
1094
motionCache->root = mev->u.keyButtonPointer.root;
1095
motionCache->event = mev->u.keyButtonPointer.event;
1096
motionCache->child = mev->u.keyButtonPointer.child;
1097
motionCache->state = mev->u.keyButtonPointer.state;
1098
motionCache->sameScreen = mev->u.keyButtonPointer.sameScreen;
1099
motionCache->sequenceNumber = mev->u.u.sequenceNumber;
1100
motionCache->time = mev->u.keyButtonPointer.time;
1101
motionCache->rootX = mev->u.keyButtonPointer.rootX;
1102
motionCache->rootY = mev->u.keyButtonPointer.rootY;
1103
motionCache->eventX = mev->u.keyButtonPointer.eventX;
1104
motionCache->eventY = mev->u.keyButtonPointer.eventY;
1105
if (client->swapped)
1107
swaps(&motionCache->sequenceNumber, n);
1108
swapl(&motionCache->time, n);
1109
swaps(&motionCache->rootX, n);
1110
swaps(&motionCache->rootY, n);
1111
swaps(&motionCache->eventX, n);
1112
swaps(&motionCache->eventY, n);
1120
if (!client->clientGone)
1121
DoLBXReply (client, rp, len);
1122
client->awaitingSetup = FALSE;
1130
LbxIgnoreAllClients(server)
1133
if (!server->lbxIgnoringAll) {
1134
if (GrabInProgress) {
1135
server->lbxGrabInProgress = GrabInProgress;
1136
ListenToAllClients();
1138
OnlyListenToOneClient(server->serverClient);
1139
server->lbxIgnoringAll = TRUE;
1145
LbxAttendAllClients(server)
1148
if (server->lbxIgnoringAll) {
1149
ListenToAllClients();
1150
server->lbxIgnoringAll = FALSE;
1151
if (server->lbxGrabInProgress) {
1152
OnlyListenToOneClient(clients[server->lbxGrabInProgress]);
1153
server->lbxGrabInProgress = 0;
1160
LbxOnlyListenToOneClient(client)
1164
* For a multi-display proxy, there is no need to do anything -
1165
* don't want one server grab to impact the clients for a
1173
LbxListenToAllClients(server)
1177
* For a multi-display proxy, there is no need to do anything -
1178
* don't want one server grab to impact the clients for a
1186
ProxyWorkProc(dummy, index)
1191
xLbxAllowMotionReq req;
1193
if ((server = servers[index]) == 0)
1195
if (!server->initialized)
1198
if (server->motion_allowed) {
1199
DBG(DBG_CLIENT, (stderr, "allow %d motion events\n",
1200
server->motion_allowed));
1201
req.reqType = server->lbxReq;
1202
req.lbxReqType = X_LbxAllowMotion;
1204
req.num = server->motion_allowed;
1205
server->motion_allowed = 0;
1206
WriteToClient(server->serverClient, sizeof(req), &req);
1208
/* Need to flush the output buffers before we flush compression buffer */
1209
if (NewOutputPending)
1212
if (server->compHandle) {
1213
if (server->lbxNegOpt.streamOpts.streamCompInputAvail(server->fd))
1214
AvailableClientInput(server->serverClient);
1215
if (server->lbxNegOpt.streamOpts.streamCompFlush(server->fd) != 0)
1216
MarkConnectionWriteBlocked(server->serverClient);
1219
* If we've got stuff remaining in the output buffers to the server, then
1220
* don't allow reads from any other clients, otherwise we could overflow.
1222
if (PendingClientOutput(server->serverClient))
1223
LbxIgnoreAllClients(server);
1225
LbxAttendAllClients(server);
1230
Bool reconnectAfterCloseServer = FALSE;
1234
ClientPtr client; /* This client is connected to a display server */
1240
DBG(DBG_CLOSE, (stderr, "closing down server\n"));
1242
server = client->server;
1243
servers[server->index] = 0;
1244
LBXFreeDeltaCache(&server->indeltas);
1245
LBXFreeDeltaCache(&server->outdeltas);
1246
if (server->compHandle)
1247
server->lbxNegOpt.streamOpts.streamCompFreeHandle(server->compHandle);
1250
* If another server is still active, don't terminate
1252
for (found = 0, i = 0; i < lbxMaxServers; i++) {
1258
if (!found && !reconnectAfterCloseServer)
1259
dispatchException |= DE_TERMINATE;
1262
* Close all of the "real" clients for this server
1264
for (i = 1; i < currentMaxClients; i++) {
1266
clients[i] != client &&
1267
clients[i]->server == server) {
1269
client->clientGone = TRUE;
1270
CloseClient (clients[i]);
1271
FreeClientResources (clients[i]);
1272
CloseDownConnection (clients[i]);
1273
if (clients[i]->index < nextFreeClientID)
1274
nextFreeClientID = clients[i]->index;
1275
clients[i] = NullClient;
1278
while (!clients[currentMaxClients-1])
1279
currentMaxClients--;
1284
* Need to remove this server's listen port(s)
1286
for (i=0; i < MAXTRANSPORTS; i++)
1287
if (server->listen_fds[i] != -1) {
1288
close (server->listen_fds[i]);
1289
FD_CLR (server->listen_fds[i], &WellKnownConnections);
1290
FD_CLR (server->listen_fds[i], &AllSockets);
1293
/* remove all back pointers */
1294
for (i = 1; i < currentMaxClients; i++) {
1295
if (clients[i] && clients[i]->server == server)
1296
clients[i]->server = NULL;
1300
* Try to reconnect to this server
1302
if (reconnectAfterCloseServer && !ConnectToServer (server->display_name)) {
1304
fprintf (stderr, "could not reconnect to '%s'\n", server->display_name);
1306
if (!found && !proxyMngr)
1308
* There is no need to continue if there is no proxyManager
1310
dispatchException |= DE_TERMINATE;
1313
if (server->display_name)
1314
free (server->display_name);
1315
if (server->proxy_name)
1316
free (server->proxy_name);
1317
xfree (server->requestVector);
1320
CloseDownFileDescriptor(client);
1322
isItTimeToYield = 1;
1327
StartProxyReply(server, rep)
1329
xLbxStartReply *rep;
1333
replylen = (rep->length << 2) + sz_xLbxStartReply - sz_xLbxStartReplyHdr;
1334
if (rep->nOpts == 0xff) {
1335
fprintf(stderr, "WARNING: option negotiation failed - using defaults\n");
1337
} else if (LbxOptParseReply(server, rep->nOpts,
1338
(unsigned char *)&rep->optDataStart, replylen) < 0) {
1339
FatalError("Bad options from server");
1343
fprintf(stderr, "server: N = %d, maxlen = %d, proxy: N = %d, maxlen = %d\n",
1344
server->lbxNegOpt.serverDeltaN, server->lbxNegOpt.serverDeltaMaxLen,
1345
server->lbxNegOpt.proxyDeltaN, server->lbxNegOpt.proxyDeltaMaxLen);
1348
LBXInitDeltaCache(&server->indeltas, server->lbxNegOpt.serverDeltaN,
1349
server->lbxNegOpt.serverDeltaMaxLen);
1350
LBXInitDeltaCache(&server->outdeltas, server->lbxNegOpt.proxyDeltaN,
1351
server->lbxNegOpt.proxyDeltaMaxLen);
1352
QueueWorkProc(ProxyWorkProc, NULL, (pointer)(long) server->index);
1355
fprintf(stderr, "squishing = %d\n", server->lbxNegOpt.squish);
1356
fprintf(stderr, "useTags = %d\n", server->lbxNegOpt.useTags);
1359
TagsInit(server, server->lbxNegOpt.useTags);
1361
if (!server->lbxNegOpt.useTags)
1363
ProcVector[X_GetModifierMapping] = ProcStandardRequest;
1364
ProcVector[X_GetKeyboardMapping] = ProcStandardRequest;
1365
ProcVector[X_QueryFont] = ProcStandardRequest;
1366
ProcVector[X_ChangeProperty] = ProcStandardRequest;
1367
ProcVector[X_GetProperty] = ProcStandardRequest;
1370
if (server->lbxNegOpt.streamOpts.streamCompInit) {
1371
unsigned char *extra = (unsigned char *) rep;
1372
int len = sizeof(xReply) + (rep->length << 2);
1373
int left = BytesInClientBuffer(server->serverClient);
1375
server->compHandle =
1376
(*server->lbxNegOpt.streamOpts.streamCompInit) (
1377
server->fd, server->lbxNegOpt.streamOpts.streamCompArg);
1378
SwitchConnectionFuncs(server->serverClient,
1379
server->lbxNegOpt.streamOpts.streamCompRead,
1380
server->lbxNegOpt.streamOpts.streamCompWriteV);
1382
server->lbxNegOpt.streamOpts.streamCompStuffInput(server->fd,
1385
SkipInClientBuffer(server->serverClient, left + len, 0);
1386
StartOutputCompression(server->serverClient,
1387
server->lbxNegOpt.streamOpts.streamCompOn,
1388
server->lbxNegOpt.streamOpts.streamCompOff);
1390
server->initialized = TRUE;
1391
MakeClientGrabImpervious(server->serverClient);
1393
if (SendInternAtoms(server))
1394
ExpectServerReply (server, InternAtomsReply);
1397
SendInitLBXPackets(server);
1400
* Now the proxy is ready to accept connections from clients.
1403
(void) ListenWellKnownSockets ();
1413
xLbxStartProxyReq *n = (xLbxStartProxyReq *) buf;
1416
n->reqType = server->lbxReq;
1417
n->lbxReqType = X_LbxStartProxy;
1418
reqlen = LbxOptBuildReq(server, buf + sz_xLbxStartProxyReq);
1419
assert(reqlen > 0 && reqlen + sz_xLbxStartProxyReq <= 1024);
1420
n->length = (reqlen + sz_xLbxStartProxyReq + 3) >> 2;
1422
* Don't call WriteToServer because we don't want to switch.
1424
WriteToClient(server->serverClient, n->length << 2, (char *) n);
1425
server->serverClient->sequence++;
1426
ExpectServerReply(server, StartProxyReply);
1427
while (NewOutputPending)
1432
InitServer (dpy_name, i, server, sequencep)
1440
DBG(DBG_IO, (stderr, "making server connection\n"));
1441
server->dpy = DisplayOpen (dpy_name,
1446
if (!server->dpy) return FALSE;
1448
server->fd = DisplayConnectionNumber (server->dpy);
1449
server->compHandle = NULL;
1450
server->initialized = FALSE;
1451
server->prev_exec = clients[0];
1452
server->send = clients[0];
1453
server->recv = clients[0];
1454
server->motion_allowed = 0;
1455
server->wm_running = FALSE;
1456
server->extensions = NULL;
1459
* Initialize the atom fields
1461
server->atom_control_count = 0;
1462
server->atom_control = NULL;
1463
LBXReadAtomsFile(server);
1466
* Initialize global and property caches
1468
server->num_caches = 0;
1472
* The ProcVector table contains the default functions plus any
1473
* changes that were made when the command line options were
1476
* In multi-display lbxproxy, each server may have different
1477
* lbx options that are negotiated. Consequently, a version
1478
* of ProcVector must be maintained for each server. The field
1479
* requestVector is used for this purpose.
1481
* When a client connects, its requestVector will be set to its
1482
* server's requestVector.
1484
server->requestVector = (int (**)()) xalloc (sizeof (ProcVector));
1485
if (!server->requestVector) return FALSE;
1486
memcpy (server->requestVector, ProcVector, sizeof (ProcVector));
1489
* Initialize the resource fields
1491
server->lastLbxClientIndexLookup = NULL;
1494
* Initialize the grab state variables
1496
server->lbxIgnoringAll = 0;
1497
server->lbxGrabInProgress = 0;
1503
ConnectToServer(dpy_name)
1510
static int been_there;
1511
static char my_host[250];
1512
char proxy_address[250+6];
1515
struct utsname name;
1518
for (i = 0; i < lbxMaxServers; i++)
1521
if (i == lbxMaxServers) {
1523
SendGetProxyAddrReply( PM_iceConn, PM_Unable, NULL,
1524
"too many servers" );
1527
server = (XServerPtr) xalloc(sizeof(XServerRec));
1530
SendGetProxyAddrReply( PM_iceConn, PM_Unable, NULL,
1531
"memory allocation failure");
1534
bzero(server, sizeof(XServerRec));
1536
if (!InitServer (dpy_name, i, server, &sequence)) {
1538
(void) snprintf (proxy_address, sizeof(proxy_address),
1539
"could not connect to server '%s'",
1541
SendGetProxyAddrReply( PM_iceConn, PM_Failure, NULL, proxy_address);
1548
* Create the socket(s) this display will listen on
1550
for (j=0; j < MAXTRANSPORTS; j++)
1551
server->listen_fds[j] = -1;
1552
CreateServerSockets(server->listen_fds);
1555
* Generate the proxy address and save the host name part
1557
if (!been_there || i == 0) {
1560
clients[0]->server = server;
1564
(void) snprintf(my_host,sizeof(my_host),"%s",name.nodename);
1566
(void) gethostname (my_host,sizeof(my_host));
1569
if (snprintf (proxy_address, sizeof(proxy_address) ,"%s:%s", my_host,
1570
display) >= sizeof(proxy_address)) {
1571
(void) snprintf (proxy_address, sizeof(proxy_address),
1572
"display name too long");
1573
SendGetProxyAddrReply( PM_iceConn, PM_Failure, NULL, proxy_address);
1577
servers[i] = server;
1579
sc = AllocNewConnection(server->fd, -1, TRUE, NULL);
1580
sc->server = server;
1581
sc->public.requestLength = ServerRequestLength;
1583
sc->requestVector = ServerVector;
1584
sc->awaitingSetup = FALSE;
1585
sc->sequence = sequence;
1588
* AllocNewConn didn't initialize the client resources so
1589
* it needs to be done here
1591
InitClientResources(sc);
1593
server->serverClient = sc;
1594
server->proxy_name = strdup (proxy_address);
1596
server->display_name = strdup (dpy_name);
1601
SendGetProxyAddrReply( PM_iceConn, PM_Success, proxy_address, NULL );