~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/lbxproxy/di/dispatch.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: dispatch.c,v 1.3 2000/08/17 19:53:55 cpqbld Exp $ */
 
2
/*
 
3
 * Copyright 1992 Network Computing Devices
 
4
 * Copyright 1996 X Consortium, Inc.
 
5
 *
 
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.
 
15
 *
 
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.
 
22
 *
 
23
 */
 
24
/* $XFree86: xc/programs/lbxproxy/di/dispatch.c,v 1.6 2001/10/28 03:34:22 tsi Exp $ */
 
25
 
 
26
#include <stdio.h>
 
27
#include "assert.h"
 
28
#include "lbx.h"
 
29
#include "wire.h"
 
30
#include "swap.h"
 
31
#include "lbxext.h"
 
32
#include "util.h"
 
33
#include "resource.h"
 
34
#include "pm.h"
 
35
 
 
36
extern int (* InitialVector[3]) ();
 
37
 
 
38
static void KillAllClients(
 
39
#if NeedFunctionPrototypes
 
40
    void
 
41
#endif
 
42
);
 
43
 
 
44
static void
 
45
HandleLargeRequest(
 
46
#if NeedFunctionPrototypes
 
47
    void
 
48
#endif
 
49
);
 
50
 
 
51
int nextFreeClientID; /* always MIN free client ID */
 
52
int nClients;   /* number active clients */
 
53
char *display_name = 0;
 
54
char dispatchException = 0;
 
55
char isItTimeToYield;
 
56
Bool lbxUseLbx = TRUE;
 
57
Bool lbxCompressImages = TRUE;
 
58
Bool lbxDoAtomShortCircuiting = TRUE;
 
59
Bool lbxDoLbxGfx = TRUE;
 
60
 
 
61
extern Bool lbxWinAttr;
 
62
extern Bool lbxDoCmapGrabbing;
 
63
extern char *atomsFile;
 
64
 
 
65
#define MAJOROP ((xReq *)client->requestBuffer)->reqType
 
66
#define MINOROP ((xReq *)client->requestBuffer)->data
 
67
 
 
68
int
 
69
Dispatch ()
 
70
{
 
71
    register int        *clientReady;     /* array of request ready clients */
 
72
    register int        result = 0;
 
73
    register ClientPtr  client;
 
74
    register int        nready;
 
75
 
 
76
    nextFreeClientID = 2;
 
77
    nClients = 0;
 
78
 
 
79
    clientReady = (int *) xalloc(sizeof(int) * MaxClients);
 
80
    if (!clientReady)
 
81
        FatalError("couldn't create client ready array");
 
82
 
 
83
    while (!dispatchException)
 
84
    {
 
85
        if (numLargeRequestsInQueue == 0) {
 
86
            /*
 
87
             * There are no pending large requests, so do blocking read.
 
88
             */
 
89
 
 
90
            nready = WaitForSomething(clientReady, FALSE /* block */);
 
91
 
 
92
        } else {
 
93
            /*
 
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
 
96
             * large request.
 
97
             */
 
98
 
 
99
            nready = WaitForSomething(clientReady, TRUE  /* poll */);
 
100
 
 
101
            if (!nready && numLargeRequestsInQueue)
 
102
                HandleLargeRequest ();
 
103
        }
 
104
 
 
105
       /***************** 
 
106
        *  Handle events in round robin fashion, doing input between 
 
107
        *  each round 
 
108
        *****************/
 
109
 
 
110
        while (!dispatchException && (--nready >= 0))
 
111
        {
 
112
            client = clients[clientReady[nready]];
 
113
            if (! client)
 
114
            {
 
115
                /* KillClient can cause this to happen */
 
116
                continue;
 
117
            }
 
118
            isItTimeToYield = FALSE;
 
119
 
 
120
            while (!isItTimeToYield)
 
121
            {
 
122
                /* now, finally, deal with client requests */
 
123
 
 
124
                result = ReadRequestFromClient(client);
 
125
                if (result <= 0) 
 
126
                {
 
127
                    if (result < 0)
 
128
                        CloseDownClient(client);
 
129
                    break;
 
130
                }
 
131
 
 
132
                client->sequence++;
 
133
#ifdef DEBUG
 
134
                if (client->requestLogIndex == MAX_REQUEST_LOG)
 
135
                    client->requestLogIndex = 0;
 
136
                client->requestLog[client->requestLogIndex] = MAJOROP;
 
137
                client->requestLogIndex++;
 
138
#endif
 
139
                client->sequenceNumber++;
 
140
                result = (* client->requestVector[MAJOROP])(client);
 
141
            
 
142
                if (result != Success) 
 
143
                {
 
144
                    if (client->noClientException != Success)
 
145
                        CloseDownClient(client);
 
146
                    else
 
147
                        SendErrorToClient(client, MAJOROP, MINOROP,
 
148
                                          client->errorValue, result);
 
149
                    break;
 
150
                }
 
151
            }
 
152
            if (result >= 0 && client != client->server->serverClient)
 
153
                client->server->prev_exec = client;
 
154
            FlushAllOutput();
 
155
        }
 
156
    }
 
157
    KillAllClients();
 
158
    LbxCleanupSession();
 
159
    xfree (clientReady);
 
160
    dispatchException &= ~DE_RESET;
 
161
    return (dispatchException & DE_TERMINATE);
 
162
}
 
163
 
 
164
void
 
165
SendErrorToClient(client, majorCode, minorCode, resId, errorCode)
 
166
    ClientPtr client;
 
167
    unsigned int majorCode;
 
168
    unsigned int minorCode;
 
169
    XID resId;
 
170
    int errorCode;
 
171
{
 
172
    xError      rep;
 
173
    int         n;
 
174
 
 
175
    rep.type = X_Error;
 
176
    rep.sequenceNumber = LBXSequenceNumber(client);
 
177
    rep.errorCode = errorCode;
 
178
    rep.majorCode = majorCode;
 
179
    rep.minorCode = minorCode;
 
180
    rep.resourceID = resId;
 
181
 
 
182
    if (client->swapped) {
 
183
        swaps(&rep.sequenceNumber, n);
 
184
        swaps(&rep.minorCode, n);
 
185
        swaps(&rep.resourceID, n);
 
186
    }
 
187
 
 
188
    if (LBXCacheSafe(client)) {
 
189
        FinishLBXRequest(client, REQ_YANK);
 
190
        WriteToClient(client, sizeof(rep), (char *)&rep);
 
191
    } else {
 
192
        if (!LBXCanDelayReply(client))
 
193
            SendLbxSync(client);
 
194
        FinishLBXRequest(client, REQ_YANKLATE);
 
195
        SaveReplyData(client, (xReply *) &rep, 0, NULL);
 
196
    }
 
197
}
 
198
 
 
199
/************************
 
200
 * int NextAvailableClient(ospriv)
 
201
 *
 
202
 * OS dependent portion can't assign client id's because of CloseDownModes.
 
203
 * Returns NULL if there are no free clients.
 
204
 *************************/
 
205
 
 
206
ClientPtr
 
207
NextAvailableClient(ospriv, connect_fd)
 
208
    pointer ospriv;
 
209
    int connect_fd;
 
210
{
 
211
    register int i;
 
212
    register ClientPtr client;
 
213
    xReq data;
 
214
    static int been_there;
 
215
 
 
216
    if (!been_there) {
 
217
       nextFreeClientID = 1; /* The first client is serverClient */
 
218
       been_there++;
 
219
    }
 
220
    i = nextFreeClientID;
 
221
    if (i == MAXCLIENTS)
 
222
        return (ClientPtr)NULL;
 
223
    clients[i] = client = (ClientPtr)xcalloc(sizeof(ClientRec));
 
224
    if (!client)
 
225
        return (ClientPtr)NULL;
 
226
    client->index = i;
 
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;
 
235
 
 
236
    /*
 
237
     * Use the fd the client connected on as a search key to find the 
 
238
     * associated display for this client
 
239
     */
 
240
    if (connect_fd != -1)
 
241
    {
 
242
        int j, k, found = 0;
 
243
        for (j=0; j < lbxMaxServers; j++)
 
244
        {
 
245
            if (servers[j])
 
246
            {
 
247
                for (k=0; k < MAXTRANSPORTS; k++)
 
248
                   if (servers[j]->listen_fds[k] == connect_fd)
 
249
                   {
 
250
                       found = 1;
 
251
                       break;
 
252
                   }
 
253
            }
 
254
            if (found)
 
255
                break;
 
256
        }
 
257
        if (!found) {
 
258
            fprintf (stderr, "Cannot determine a client's transport connection\n");
 
259
            return (ClientPtr) NULL;
 
260
        }
 
261
        client->server = servers[j];
 
262
    }
 
263
 
 
264
    if (client->server && !InitClientResources(client))
 
265
    {
 
266
        xfree(client);
 
267
        return (ClientPtr)NULL;
 
268
    }
 
269
 
 
270
    if (i == currentMaxClients)
 
271
        currentMaxClients++;
 
272
    while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
 
273
        nextFreeClientID++;
 
274
    if (client->server)
 
275
    {
 
276
        data.reqType = 1;
 
277
        data.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
 
278
        if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
 
279
        {
 
280
            xfree (client);
 
281
            return (ClientPtr) NULL;
 
282
        }
 
283
    }
 
284
    return(client);
 
285
}
 
286
 
 
287
int
 
288
ProcInitialConnection(client)
 
289
    register ClientPtr client;
 
290
{
 
291
    REQUEST(xReq);
 
292
    register xConnClientPrefix *prefix;
 
293
    int whichbyte = 1;
 
294
 
 
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')))
 
300
    {
 
301
        client->swapped = TRUE;
 
302
        SwapConnClientPrefix(prefix);
 
303
    }
 
304
    stuff->reqType = 2;
 
305
    stuff->length += ((prefix->nbytesAuthProto + 3) >> 2) +
 
306
                     ((prefix->nbytesAuthString + 3) >> 2);
 
307
    if (client->swapped) {
 
308
        swaps(&stuff->length, whichbyte);
 
309
    }
 
310
    ResetCurrentRequest(client);
 
311
    return (client->noClientException);
 
312
}
 
313
 
 
314
int
 
315
ProcEstablishConnection(client)
 
316
    register ClientPtr client;
 
317
{
 
318
    register xConnClientPrefix *prefix;
 
319
    register int i;
 
320
    int         len;
 
321
 
 
322
    REQUEST(xReq);
 
323
 
 
324
    prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
 
325
 
 
326
    nClients++;
 
327
    client->requestVector = client->server->requestVector;
 
328
    client->sequence = 0;
 
329
    client->sequenceNumber = 0;
 
330
    client->largeRequest = NULL;
 
331
 
 
332
    /* wait for X server to kill client */
 
333
    client->closeDownMode = RetainPermanent;
 
334
 
 
335
    /*
 
336
     * NewClient outputs the LbxNewClient request header - have to follow it
 
337
     * up with the setup connection info.
 
338
     */
 
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);
 
344
    }
 
345
    len = (stuff->length << 2) - sz_xReq;
 
346
    if (!NewClient(client, len))
 
347
        return (client->noClientException = -1);
 
348
 
 
349
    WriteToServer(client->server->serverClient, len, (char *) prefix, 
 
350
                  TRUE, FALSE);
 
351
 
 
352
    /*
 
353
     * Can't allow any requests to be passed on to the server until the
 
354
     * connection setup reply has been received.
 
355
     */
 
356
    IgnoreClient(client);
 
357
 
 
358
    return (client->noClientException);
 
359
}
 
360
 
 
361
/**********************
 
362
 * CloseDownClient
 
363
 *
 
364
 *  Client can either mark his resources destroy or retain.  If retained and
 
365
 *  then killed again, the client is really destroyed.
 
366
 *********************/
 
367
 
 
368
Bool resetAfterLastClient = FALSE;
 
369
Bool terminateAfterLastClient = FALSE;
 
370
 
 
371
void
 
372
CloseDownClient(client)
 
373
    register ClientPtr client;
 
374
{
 
375
    if (!client->clientGone)
 
376
    {
 
377
        CloseClient (client);
 
378
        
 
379
        
 
380
        /* X server is telling us this client is dead */
 
381
        if (client->closeDownMode == DestroyAll)
 
382
        {
 
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) &&
 
393
                (--nClients == 0))
 
394
            {
 
395
                if (resetAfterLastClient)
 
396
                    dispatchException |= DE_RESET;
 
397
                else if (terminateAfterLastClient)
 
398
                    dispatchException |= DE_TERMINATE;
 
399
            }
 
400
            xfree(client);
 
401
        }
 
402
        else
 
403
        {
 
404
            client->clientGone = TRUE;
 
405
            CloseDownConnection(client);
 
406
            --nClients;
 
407
        }
 
408
    }
 
409
    else
 
410
    {
 
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;
 
418
        xfree(client);
 
419
        if (nClients == 0)
 
420
        {
 
421
            if (resetAfterLastClient)
 
422
                dispatchException |= DE_RESET;
 
423
            else if (terminateAfterLastClient)
 
424
                dispatchException |= DE_TERMINATE;
 
425
        }
 
426
    }
 
427
 
 
428
    while (!clients[currentMaxClients-1])
 
429
      currentMaxClients--;
 
430
}
 
431
 
 
432
static void
 
433
KillAllClients()
 
434
{
 
435
    int i;
 
436
    for (i=1; i<currentMaxClients; i++)
 
437
    {
 
438
        if (clients[i])
 
439
        {
 
440
            clients[i]->closeDownMode = DestroyAll;   
 
441
            CloseDownClient(clients[i]);
 
442
        }
 
443
    }
 
444
}
 
445
 
 
446
extern void (*ZeroPadReqVector[128]) ();
 
447
 
 
448
int
 
449
ProcStandardRequest (client)
 
450
    ClientPtr   client;
 
451
{
 
452
    REQUEST(xReq);
 
453
    void (*zeroPadProc)();
 
454
    extern int lbxZeroPad;
 
455
 
 
456
    if (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);
 
461
    return Success;
 
462
}
 
463
 
 
464
/* ARGSUSED */
 
465
int
 
466
ProcBadRequest (client)
 
467
    ClientPtr   client;
 
468
{
 
469
    return BadRequest;
 
470
}
 
471
 
 
472
/*
 
473
 * Turn off optional features.  Some features, like tags, will be turned
 
474
 * off after option negotiation.
 
475
 */
 
476
 
 
477
void
 
478
AdjustProcVector()
 
479
{
 
480
    int         i;
 
481
 
 
482
    /*
 
483
     * to turn off all LBX request reencodings, set all proc vectors to
 
484
     * ProcStandardRequest
 
485
     */
 
486
    if (!lbxUseLbx) {
 
487
        for (i = 1; i < 256; i++) {
 
488
            ProcVector[i] = ProcStandardRequest;
 
489
        }
 
490
    }
 
491
 
 
492
    if (!atomsFile)
 
493
        ProcVector[X_ChangeWindowAttributes] = ProcStandardRequest;
 
494
 
 
495
    if (!lbxCompressImages) {
 
496
        ProcVector[X_PutImage] = ProcStandardRequest;
 
497
        ProcVector[X_GetImage] = ProcStandardRequest;
 
498
    }
 
499
 
 
500
    if (!lbxDoAtomShortCircuiting) {
 
501
        ProcVector[X_InternAtom] = ProcStandardRequest;
 
502
        ProcVector[X_GetAtomName] = ProcStandardRequest;
 
503
    }
 
504
 
 
505
    if (!lbxDoCmapGrabbing)
 
506
    {
 
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;
 
516
    }
 
517
 
 
518
    if (!lbxDoLbxGfx) {
 
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;
 
533
    }
 
534
 
 
535
    if (!lbxWinAttr)
 
536
    {
 
537
        ProcVector[X_GetWindowAttributes] = ProcStandardRequest;
 
538
        ProcVector[X_GetGeometry] = ProcStandardRequest;
 
539
    }
 
540
}
 
541
 
 
542
 
 
543
static void
 
544
HandleLargeRequest ()
 
545
 
 
546
{
 
547
    LbxLargeRequestRec *largeRequest = largeRequestQueue[0];
 
548
    ClientPtr client = largeRequest->client;
 
549
    int bytesLeft, chunkSize;
 
550
 
 
551
    /*
 
552
     * Process the first large request on the queue.  If this is the first
 
553
     * chunk of a large request, send an LbxBeginLargeRequest message.
 
554
     */
 
555
 
 
556
    if (largeRequest->bytesWritten == 0) {
 
557
        xLbxBeginLargeRequestReq beginReq;
 
558
        int n;
 
559
 
 
560
        beginReq.reqType = client->server->lbxReq;
 
561
        beginReq.lbxReqType = X_LbxBeginLargeRequest;
 
562
        beginReq.length = 2;
 
563
        beginReq.largeReqLength = largeRequest->totalBytes >> 2;
 
564
        if (client->swapped) {
 
565
            swapl(&beginReq.largeReqLength, n);
 
566
        }
 
567
        _write_to_server (client,
 
568
            largeRequest->compressed,
 
569
            sizeof (beginReq), (char *) &beginReq,
 
570
            FALSE, TRUE);
 
571
    }
 
572
 
 
573
    /*
 
574
     * Send a chunk of the large request using the LbxLargeRequestData message.
 
575
     */
 
576
 
 
577
    bytesLeft = largeRequest->totalBytes - largeRequest->bytesWritten;
 
578
 
 
579
    if (bytesLeft > LBX_LARGE_REQUEST_CHUNK_SIZE)
 
580
        chunkSize = LBX_LARGE_REQUEST_CHUNK_SIZE;
 
581
    else
 
582
        chunkSize = bytesLeft;
 
583
 
 
584
    if (chunkSize > 0) {
 
585
        xLbxLargeRequestDataReq dataReq;
 
586
 
 
587
        dataReq.reqType = client->server->lbxReq;
 
588
        dataReq.lbxReqType = X_LbxLargeRequestData;
 
589
        dataReq.length = 1 + (chunkSize >> 2);
 
590
 
 
591
        _write_to_server (client,
 
592
            largeRequest->compressed,
 
593
            sizeof (dataReq), (char *) &dataReq,
 
594
            FALSE, TRUE);
 
595
 
 
596
        _write_to_server (client,
 
597
            largeRequest->compressed,
 
598
            chunkSize,
 
599
            largeRequest->buf + largeRequest->bytesWritten,
 
600
            FALSE, FALSE);
 
601
 
 
602
        largeRequest->bytesWritten += chunkSize;
 
603
    }
 
604
 
 
605
    if (numLargeRequestsInQueue > 1) {
 
606
        /*
 
607
         * Move this large request to the end of the queue - this way
 
608
         * we can process large requests from other clients too.
 
609
         */
 
610
 
 
611
        memmove((char *)&largeRequestQueue[0], (char *)&largeRequestQueue[1],
 
612
                (numLargeRequestsInQueue - 1) * sizeof(LbxLargeRequestRec *));
 
613
        largeRequestQueue[numLargeRequestsInQueue - 1] = largeRequest;
 
614
    }
 
615
 
 
616
    /*
 
617
     * See if the whole request has been sent.  If yes, send an
 
618
     * LbxEndLargeRequest and re-enable input for this client.
 
619
     */
 
620
 
 
621
    if (largeRequest->bytesWritten == largeRequest->totalBytes) {
 
622
        xLbxEndLargeRequestReq endReq;
 
623
 
 
624
        endReq.reqType = client->server->lbxReq;
 
625
        endReq.lbxReqType = X_LbxEndLargeRequest;
 
626
        endReq.length = 1;
 
627
 
 
628
        _write_to_server (client,
 
629
            largeRequest->compressed,
 
630
            sizeof (endReq), (char *) &endReq,
 
631
            FALSE, TRUE);
 
632
 
 
633
        xfree ((char *) largeRequest);
 
634
        client->largeRequest = NULL;
 
635
        numLargeRequestsInQueue--;
 
636
                    
 
637
        AttendClient (client);
 
638
    }
 
639
}