1
/* $Xorg: dispatch.c,v 1.3 2000/08/17 19:53:55 cpqbld Exp $ */
3
* Copyright 1992 Network Computing Devices
4
* Copyright 1996 X Consortium, Inc.
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
10
* documentation, and that the name of NCD. not be used in advertising or
11
* publicity pertaining to distribution of the software without specific,
12
* written prior permission. NCD. makes no representations about the
13
* suitability of this software for any purpose. It is provided "as is"
14
* without express or implied warranty.
16
* NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
18
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
/* $XFree86: xc/programs/lbxproxy/di/dispatch.c,v 1.6 2001/10/28 03:34:22 tsi Exp $ */
36
extern int (* InitialVector[3]) ();
38
static void KillAllClients(
39
#if NeedFunctionPrototypes
46
#if NeedFunctionPrototypes
51
int nextFreeClientID; /* always MIN free client ID */
52
int nClients; /* number active clients */
53
char *display_name = 0;
54
char dispatchException = 0;
56
Bool lbxUseLbx = TRUE;
57
Bool lbxCompressImages = TRUE;
58
Bool lbxDoAtomShortCircuiting = TRUE;
59
Bool lbxDoLbxGfx = TRUE;
61
extern Bool lbxWinAttr;
62
extern Bool lbxDoCmapGrabbing;
63
extern char *atomsFile;
65
#define MAJOROP ((xReq *)client->requestBuffer)->reqType
66
#define MINOROP ((xReq *)client->requestBuffer)->data
71
register int *clientReady; /* array of request ready clients */
72
register int result = 0;
73
register ClientPtr client;
79
clientReady = (int *) xalloc(sizeof(int) * MaxClients);
81
FatalError("couldn't create client ready array");
83
while (!dispatchException)
85
if (numLargeRequestsInQueue == 0) {
87
* There are no pending large requests, so do blocking read.
90
nready = WaitForSomething(clientReady, FALSE /* block */);
94
* If there is no input from any clients (the only way we can
95
* check this is by polling rather than blocking), handle a
99
nready = WaitForSomething(clientReady, TRUE /* poll */);
101
if (!nready && numLargeRequestsInQueue)
102
HandleLargeRequest ();
106
* Handle events in round robin fashion, doing input between
110
while (!dispatchException && (--nready >= 0))
112
client = clients[clientReady[nready]];
115
/* KillClient can cause this to happen */
118
isItTimeToYield = FALSE;
120
while (!isItTimeToYield)
122
/* now, finally, deal with client requests */
124
result = ReadRequestFromClient(client);
128
CloseDownClient(client);
134
if (client->requestLogIndex == MAX_REQUEST_LOG)
135
client->requestLogIndex = 0;
136
client->requestLog[client->requestLogIndex] = MAJOROP;
137
client->requestLogIndex++;
139
client->sequenceNumber++;
140
result = (* client->requestVector[MAJOROP])(client);
142
if (result != Success)
144
if (client->noClientException != Success)
145
CloseDownClient(client);
147
SendErrorToClient(client, MAJOROP, MINOROP,
148
client->errorValue, result);
152
if (result >= 0 && client != client->server->serverClient)
153
client->server->prev_exec = client;
160
dispatchException &= ~DE_RESET;
161
return (dispatchException & DE_TERMINATE);
165
SendErrorToClient(client, majorCode, minorCode, resId, errorCode)
167
unsigned int majorCode;
168
unsigned int minorCode;
176
rep.sequenceNumber = LBXSequenceNumber(client);
177
rep.errorCode = errorCode;
178
rep.majorCode = majorCode;
179
rep.minorCode = minorCode;
180
rep.resourceID = resId;
182
if (client->swapped) {
183
swaps(&rep.sequenceNumber, n);
184
swaps(&rep.minorCode, n);
185
swaps(&rep.resourceID, n);
188
if (LBXCacheSafe(client)) {
189
FinishLBXRequest(client, REQ_YANK);
190
WriteToClient(client, sizeof(rep), (char *)&rep);
192
if (!LBXCanDelayReply(client))
194
FinishLBXRequest(client, REQ_YANKLATE);
195
SaveReplyData(client, (xReply *) &rep, 0, NULL);
199
/************************
200
* int NextAvailableClient(ospriv)
202
* OS dependent portion can't assign client id's because of CloseDownModes.
203
* Returns NULL if there are no free clients.
204
*************************/
207
NextAvailableClient(ospriv, connect_fd)
212
register ClientPtr client;
214
static int been_there;
217
nextFreeClientID = 1; /* The first client is serverClient */
220
i = nextFreeClientID;
222
return (ClientPtr)NULL;
223
clients[i] = client = (ClientPtr)xcalloc(sizeof(ClientRec));
225
return (ClientPtr)NULL;
227
client->closeDownMode = DestroyAll;
228
client->awaitingSetup = TRUE;
229
client->saveSet = (pointer *)NULL;
230
client->noClientException = Success;
231
client->public.requestLength = StandardRequestLength;
232
client->requestVector = InitialVector;
233
client->osPrivate = ospriv;
234
client->big_requests = TRUE;
237
* Use the fd the client connected on as a search key to find the
238
* associated display for this client
240
if (connect_fd != -1)
243
for (j=0; j < lbxMaxServers; j++)
247
for (k=0; k < MAXTRANSPORTS; k++)
248
if (servers[j]->listen_fds[k] == connect_fd)
258
fprintf (stderr, "Cannot determine a client's transport connection\n");
259
return (ClientPtr) NULL;
261
client->server = servers[j];
264
if (client->server && !InitClientResources(client))
267
return (ClientPtr)NULL;
270
if (i == currentMaxClients)
272
while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
277
data.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
278
if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
281
return (ClientPtr) NULL;
288
ProcInitialConnection(client)
289
register ClientPtr client;
292
register xConnClientPrefix *prefix;
295
prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
296
if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
297
return (client->noClientException = -1);
298
if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
299
(!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
301
client->swapped = TRUE;
302
SwapConnClientPrefix(prefix);
305
stuff->length += ((prefix->nbytesAuthProto + 3) >> 2) +
306
((prefix->nbytesAuthString + 3) >> 2);
307
if (client->swapped) {
308
swaps(&stuff->length, whichbyte);
310
ResetCurrentRequest(client);
311
return (client->noClientException);
315
ProcEstablishConnection(client)
316
register ClientPtr client;
318
register xConnClientPrefix *prefix;
324
prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
327
client->requestVector = client->server->requestVector;
328
client->sequence = 0;
329
client->sequenceNumber = 0;
330
client->largeRequest = NULL;
332
/* wait for X server to kill client */
333
client->closeDownMode = RetainPermanent;
336
* NewClient outputs the LbxNewClient request header - have to follow it
337
* up with the setup connection info.
339
/* length is still swapped */
340
if (client->swapped) {
341
swaps(&stuff->length, i);
342
/* put data back to the way server will expect it */
343
SwapConnClientPrefix((xConnClientPrefix *) prefix);
345
len = (stuff->length << 2) - sz_xReq;
346
if (!NewClient(client, len))
347
return (client->noClientException = -1);
349
WriteToServer(client->server->serverClient, len, (char *) prefix,
353
* Can't allow any requests to be passed on to the server until the
354
* connection setup reply has been received.
356
IgnoreClient(client);
358
return (client->noClientException);
361
/**********************
364
* Client can either mark his resources destroy or retain. If retained and
365
* then killed again, the client is really destroyed.
366
*********************/
368
Bool resetAfterLastClient = FALSE;
369
Bool terminateAfterLastClient = FALSE;
372
CloseDownClient(client)
373
register ClientPtr client;
375
if (!client->clientGone)
377
CloseClient (client);
380
/* X server is telling us this client is dead */
381
if (client->closeDownMode == DestroyAll)
383
client->clientGone = TRUE; /* so events aren't sent to client */
384
FreeClientResources(client);
385
CloseDownConnection(client);
386
if (ClientIsAsleep (client))
387
ClientSignal (client);
388
if (client->index < nextFreeClientID)
389
nextFreeClientID = client->index;
390
clients[client->index] = NullClient;
391
if ((client->requestVector != InitialVector) &&
392
(client->server && client->server->serverClient != client) &&
395
if (resetAfterLastClient)
396
dispatchException |= DE_RESET;
397
else if (terminateAfterLastClient)
398
dispatchException |= DE_TERMINATE;
404
client->clientGone = TRUE;
405
CloseDownConnection(client);
411
/* really kill resources this time */
412
FreeClientResources(client);
413
if (ClientIsAsleep (client))
414
ClientSignal (client);
415
if (client->index < nextFreeClientID)
416
nextFreeClientID = client->index;
417
clients[client->index] = NullClient;
421
if (resetAfterLastClient)
422
dispatchException |= DE_RESET;
423
else if (terminateAfterLastClient)
424
dispatchException |= DE_TERMINATE;
428
while (!clients[currentMaxClients-1])
436
for (i=1; i<currentMaxClients; i++)
440
clients[i]->closeDownMode = DestroyAll;
441
CloseDownClient(clients[i]);
446
extern void (*ZeroPadReqVector[128]) ();
449
ProcStandardRequest (client)
453
void (*zeroPadProc)();
454
extern int lbxZeroPad;
457
(MAJOROP < 128) && (zeroPadProc = ZeroPadReqVector[MAJOROP]))
458
(*zeroPadProc) ((void *) stuff);
459
FinishLBXRequest(client, REQ_PASSTHROUGH);
460
WriteReqToServer(client, client->req_len << 2, (char *) stuff, TRUE);
466
ProcBadRequest (client)
473
* Turn off optional features. Some features, like tags, will be turned
474
* off after option negotiation.
483
* to turn off all LBX request reencodings, set all proc vectors to
484
* ProcStandardRequest
487
for (i = 1; i < 256; i++) {
488
ProcVector[i] = ProcStandardRequest;
493
ProcVector[X_ChangeWindowAttributes] = ProcStandardRequest;
495
if (!lbxCompressImages) {
496
ProcVector[X_PutImage] = ProcStandardRequest;
497
ProcVector[X_GetImage] = ProcStandardRequest;
500
if (!lbxDoAtomShortCircuiting) {
501
ProcVector[X_InternAtom] = ProcStandardRequest;
502
ProcVector[X_GetAtomName] = ProcStandardRequest;
505
if (!lbxDoCmapGrabbing)
507
ProcVector[X_CreateColormap] = ProcStandardRequest;
508
ProcVector[X_FreeColormap] = ProcStandardRequest;
509
ProcVector[X_CopyColormapAndFree] = ProcStandardRequest;
510
ProcVector[X_AllocColor] = ProcStandardRequest;
511
ProcVector[X_AllocNamedColor] = ProcStandardRequest;
512
ProcVector[X_AllocColorCells] = ProcStandardRequest;
513
ProcVector[X_AllocColorPlanes] = ProcStandardRequest;
514
ProcVector[X_FreeColors] = ProcStandardRequest;
515
ProcVector[X_LookupColor] = ProcStandardRequest;
519
ProcVector[X_CopyArea] = ProcStandardRequest;
520
ProcVector[X_CopyPlane] = ProcStandardRequest;
521
ProcVector[X_PolyPoint] = ProcStandardRequest;
522
ProcVector[X_PolyLine] = ProcStandardRequest;
523
ProcVector[X_PolySegment] = ProcStandardRequest;
524
ProcVector[X_PolyRectangle] = ProcStandardRequest;
525
ProcVector[X_PolyArc] = ProcStandardRequest;
526
ProcVector[X_FillPoly] = ProcStandardRequest;
527
ProcVector[X_PolyFillRectangle] = ProcStandardRequest;
528
ProcVector[X_PolyFillArc] = ProcStandardRequest;
529
ProcVector[X_PolyText8] = ProcStandardRequest;
530
ProcVector[X_PolyText16] = ProcStandardRequest;
531
ProcVector[X_ImageText8] = ProcStandardRequest;
532
ProcVector[X_ImageText16] = ProcStandardRequest;
537
ProcVector[X_GetWindowAttributes] = ProcStandardRequest;
538
ProcVector[X_GetGeometry] = ProcStandardRequest;
544
HandleLargeRequest ()
547
LbxLargeRequestRec *largeRequest = largeRequestQueue[0];
548
ClientPtr client = largeRequest->client;
549
int bytesLeft, chunkSize;
552
* Process the first large request on the queue. If this is the first
553
* chunk of a large request, send an LbxBeginLargeRequest message.
556
if (largeRequest->bytesWritten == 0) {
557
xLbxBeginLargeRequestReq beginReq;
560
beginReq.reqType = client->server->lbxReq;
561
beginReq.lbxReqType = X_LbxBeginLargeRequest;
563
beginReq.largeReqLength = largeRequest->totalBytes >> 2;
564
if (client->swapped) {
565
swapl(&beginReq.largeReqLength, n);
567
_write_to_server (client,
568
largeRequest->compressed,
569
sizeof (beginReq), (char *) &beginReq,
574
* Send a chunk of the large request using the LbxLargeRequestData message.
577
bytesLeft = largeRequest->totalBytes - largeRequest->bytesWritten;
579
if (bytesLeft > LBX_LARGE_REQUEST_CHUNK_SIZE)
580
chunkSize = LBX_LARGE_REQUEST_CHUNK_SIZE;
582
chunkSize = bytesLeft;
585
xLbxLargeRequestDataReq dataReq;
587
dataReq.reqType = client->server->lbxReq;
588
dataReq.lbxReqType = X_LbxLargeRequestData;
589
dataReq.length = 1 + (chunkSize >> 2);
591
_write_to_server (client,
592
largeRequest->compressed,
593
sizeof (dataReq), (char *) &dataReq,
596
_write_to_server (client,
597
largeRequest->compressed,
599
largeRequest->buf + largeRequest->bytesWritten,
602
largeRequest->bytesWritten += chunkSize;
605
if (numLargeRequestsInQueue > 1) {
607
* Move this large request to the end of the queue - this way
608
* we can process large requests from other clients too.
611
memmove((char *)&largeRequestQueue[0], (char *)&largeRequestQueue[1],
612
(numLargeRequestsInQueue - 1) * sizeof(LbxLargeRequestRec *));
613
largeRequestQueue[numLargeRequestsInQueue - 1] = largeRequest;
617
* See if the whole request has been sent. If yes, send an
618
* LbxEndLargeRequest and re-enable input for this client.
621
if (largeRequest->bytesWritten == largeRequest->totalBytes) {
622
xLbxEndLargeRequestReq endReq;
624
endReq.reqType = client->server->lbxReq;
625
endReq.lbxReqType = X_LbxEndLargeRequest;
628
_write_to_server (client,
629
largeRequest->compressed,
630
sizeof (endReq), (char *) &endReq,
633
xfree ((char *) largeRequest);
634
client->largeRequest = NULL;
635
numLargeRequestsInQueue--;
637
AttendClient (client);