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

« back to all changes in this revision

Viewing changes to unix/xc/programs/lbxproxy/di/wire.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: wire.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
 
2
/*
 
3
 
 
4
Copyright 1998  The Open Group
 
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.
 
11
 
 
12
The above copyright notice and this permission notice shall be included in
 
13
all copies or substantial portions of the Software.
 
14
 
 
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.
 
21
 
 
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.
 
25
 
 
26
*/
 
27
/*
 
28
 * Copyright 1992 Network Computing Devices
 
29
 *
 
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.
 
39
 *
 
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.
 
46
 *
 
47
 */
 
48
/* $XFree86: xc/programs/lbxproxy/di/wire.c,v 1.14 2002/09/19 13:22:03 tsi Exp $ */
 
49
 
 
50
#include "lbx.h"
 
51
#include <stdio.h>
 
52
#include <stdlib.h>
 
53
#include "wire.h"
 
54
#include "tags.h"
 
55
#include "colormap.h"
 
56
#include "init.h"
 
57
#ifndef Lynx
 
58
#include <sys/uio.h>
 
59
#else
 
60
#include <uio.h>
 
61
#endif
 
62
#include <errno.h>
 
63
#include "proxyopts.h"
 
64
#include "swap.h"
 
65
#include "assert.h"
 
66
#include "os.h"
 
67
#include "resource.h"
 
68
#include "colormap.h"
 
69
#include "lbxext.h"
 
70
#include "atomcache.h"
 
71
#include "util.h"
 
72
#include "pm.h"
 
73
#include "misc.h"
 
74
 
 
75
#include <X11/ICE/ICElib.h>
 
76
#ifdef BIGREQS
 
77
#include "bigreqstr.h"
 
78
#endif
 
79
 
 
80
/*
 
81
 * The following include for utsname.h is from lib/xtrans
 
82
 */
 
83
#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4)
 
84
#define NEED_UTSNAME
 
85
#include <sys/utsname.h>        /* uname() */
 
86
#else
 
87
#include <unistd.h>             /* gethostname() */
 
88
#endif
 
89
 
 
90
#ifdef LBX_STATS
 
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;
 
97
#endif
 
98
 
 
99
/*
 
100
 * Local constants
 
101
 */
 
102
#define MAXBYTESDIFF            8
 
103
#define PM_Unable  0
 
104
#define PM_Success 1
 
105
#define PM_Failure 2
 
106
 
 
107
/*
 
108
 * Global vars
 
109
 */
 
110
int lbxDebug = 0;
 
111
 
 
112
/*
 
113
 * Local functions
 
114
 */
 
115
static void LbxOnlyListenToOneClient();
 
116
static void LbxListenToAllClients();
 
117
 
 
118
/*
 
119
 * Any request that could be delta compressed comes through here
 
120
 */
 
121
void
 
122
WriteReqToServer(client, len, buf, checkLargeRequest)
 
123
    ClientPtr   client;
 
124
    int         len;
 
125
    char       *buf;
 
126
    Bool        checkLargeRequest;
 
127
{
 
128
    XServerPtr  server = client->server;
 
129
    xLbxDeltaReq *p = (xLbxDeltaReq *) server->tempdeltabuf;
 
130
    int         diffs;
 
131
    int         cindex;
 
132
    int         newlen;
 
133
    Bool        written = FALSE;
 
134
 
 
135
#ifdef LBX_STATS
 
136
    delta_out_total++;
 
137
#endif
 
138
 
 
139
    if (DELTA_CACHEABLE(&server->outdeltas, len)) {
 
140
 
 
141
#ifdef LBX_STATS
 
142
        delta_out_attempts++;
 
143
#endif
 
144
 
 
145
        if ((diffs = LBXDeltaMinDiffs(&server->outdeltas, (unsigned char *)buf,
 
146
                        len, min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1),
 
147
                                      &cindex)) >= 0) {
 
148
 
 
149
#ifdef LBX_STATS
 
150
            delta_out_hits++;
 
151
#endif
 
152
 
 
153
            LBXEncodeDelta(&server->outdeltas, (unsigned char *)buf, diffs,
 
154
                           cindex, &server->tempdeltabuf[sz_xLbxDeltaReq]);
 
155
            p->reqType = server->lbxReq;
 
156
            p->lbxReqType = X_LbxDelta;
 
157
            p->diffs = diffs;
 
158
            p->cindex = cindex;
 
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);
 
163
            written = TRUE;
 
164
        }
 
165
        LBXAddDeltaOut(&server->outdeltas, (unsigned char *)buf, len);
 
166
    }
 
167
    if (!written) {
 
168
#ifdef BIGREQS
 
169
        if (len > (0xffff << 2)) {
 
170
            xBigReq bigreq;
 
171
            bigreq.reqType = ((xReq *)buf)->reqType;
 
172
            bigreq.data = ((xReq *)buf)->data;
 
173
            bigreq.zero = 0;
 
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);
 
179
            return;
 
180
        }
 
181
#endif
 
182
        WriteToServer(client, len, buf, TRUE, checkLargeRequest);
 
183
    }
 
184
}
 
185
 
 
186
void
 
187
_write_to_server(client, compressed, len, buf, checkLarge, startOfRequest)
 
188
    ClientPtr   client;
 
189
    Bool        compressed;
 
190
    int         len;
 
191
    char       *buf;
 
192
    Bool        checkLarge;
 
193
    Bool        startOfRequest;
 
194
{
 
195
    XServerPtr  server = client->server;
 
196
    unsigned reqSize;
 
197
 
 
198
    if (server->serverClient->clientGone)
 
199
        return;
 
200
 
 
201
    if (checkLarge && client != clients[0] && nClients > 1 &&
 
202
        ((client != server->prev_exec) || numLargeRequestsInQueue)) {
 
203
        /*
 
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.
 
207
         *
 
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.
 
211
         *
 
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
 
215
         * history).
 
216
         */
 
217
 
 
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;
 
223
 
 
224
            if (!reqSize)
 
225
                reqSize = ((xBigReq *)buf)->length << 2;
 
226
            largeRequest = (LbxLargeRequestRec *)
 
227
                xalloc (sizeof (LbxLargeRequestRec) + reqSize);
 
228
 
 
229
            /*
 
230
             * Add this large request to the queue
 
231
             */
 
232
 
 
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;
 
242
 
 
243
            largeRequestQueue[numLargeRequestsInQueue++] = largeRequest;
 
244
 
 
245
            /*
 
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.
 
249
             */
 
250
 
 
251
            if (reqSize == len)
 
252
                IgnoreClient(client);
 
253
            
 
254
            return;
 
255
        } else if (client->largeRequest) {
 
256
 
 
257
            /*
 
258
             * Append to the large request
 
259
             */
 
260
 
 
261
            char *dst = client->largeRequest->buf +
 
262
                client->largeRequest->bytesRead;
 
263
            memcpy (dst, buf, len);
 
264
            client->largeRequest->bytesRead += len;
 
265
 
 
266
            /*
 
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.
 
270
             */
 
271
 
 
272
            if (client->largeRequest->bytesRead ==
 
273
                client->largeRequest->totalBytes)
 
274
                IgnoreClient(client);
 
275
 
 
276
            return;
 
277
        }
 
278
    }
 
279
 
 
280
    if (server->send != client) {
 
281
        xLbxSwitchReq s;
 
282
 
 
283
        DBG(DBG_SWITCH, (stderr, "switch downstream to %d\n", client->index));
 
284
        s.reqType = server->lbxReq;
 
285
        s.lbxReqType = X_LbxSwitch;
 
286
        s.length = 2;
 
287
        s.client = client->index;
 
288
        WriteToClient(server->serverClient, sizeof(s), &s);
 
289
        server->send = client;
 
290
    }
 
291
    DBG(DBG_IO, (stderr, "downstream %d len %d\n", client->index, len));
 
292
    if (compressed || !server->compHandle)
 
293
        WriteToClient(server->serverClient, len, buf);
 
294
    else
 
295
        UncompressWriteToClient(server->serverClient, len, buf);
 
296
}
 
297
 
 
298
void
 
299
WriteToServer(client, len, buf, startOfRequest, checkLargeRequest)
 
300
    ClientPtr   client;
 
301
    int         len;
 
302
    char       *buf;
 
303
    Bool        startOfRequest;
 
304
    Bool        checkLargeRequest;
 
305
{
 
306
    _write_to_server(client, TRUE, len, buf, checkLargeRequest, startOfRequest);
 
307
}
 
308
 
 
309
void
 
310
WriteToServerUncompressed(client, len, buf, startOfRequest)
 
311
    ClientPtr   client;
 
312
    int         len;
 
313
    char       *buf;
 
314
    Bool        startOfRequest;
 
315
{
 
316
    _write_to_server(client, FALSE, len, buf, TRUE, startOfRequest);
 
317
}
 
318
 
 
319
/* all these requests may need to be swapped back to the order of
 
320
 * the client they're being executed for
 
321
 */
 
322
Bool
 
323
NewClient(client, setuplen)
 
324
    ClientPtr   client;
 
325
    int         setuplen;
 
326
{
 
327
    xLbxNewClientReq n;
 
328
    XServerPtr  server = client->server;
 
329
 
 
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;
 
337
    return TRUE;
 
338
}
 
339
 
 
340
void
 
341
CloseClient(client)
 
342
    ClientPtr   client;
 
343
{
 
344
    xLbxCloseClientReq n;
 
345
    XServerPtr  server = client->server;
 
346
 
 
347
    if (!client->server)
 
348
        return;
 
349
 
 
350
    if (client->server->serverClient == client)
 
351
        return;
 
352
    if (client->server->serverClient->clientGone)
 
353
        return;
 
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;
 
358
        n.length = 2;
 
359
        n.client = client->index;
 
360
        if (client->swapped) {
 
361
            SwapCloseClient(&n);
 
362
        }
 
363
        WriteReqToServer(client, sizeof(n), (char *) &n, TRUE);
 
364
    }
 
365
}
 
366
 
 
367
void
 
368
ModifySequence(client, num)
 
369
    ClientPtr   client;
 
370
    int         num;
 
371
{
 
372
    xLbxModifySequenceReq req;
 
373
    XServerPtr  server = client->server;
 
374
 
 
375
    if (client->server->serverClient == client)
 
376
        return;
 
377
    req.reqType = server->lbxReq;
 
378
    req.lbxReqType = X_LbxModifySequence;
 
379
    req.length = 2;
 
380
    req.adjust = num;
 
381
    if (client->swapped) {
 
382
        SwapModifySequence(&req);
 
383
    }
 
384
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
385
}
 
386
 
 
387
void
 
388
AllowMotion(client, num)
 
389
    ClientPtr   client;
 
390
    int         num;
 
391
{
 
392
    client->server->motion_allowed += num;
 
393
}
 
394
 
 
395
void
 
396
SendIncrementPixel(client, cmap, pixel)
 
397
    ClientPtr   client;
 
398
    XID         cmap;
 
399
    unsigned long pixel;
 
400
{
 
401
    xLbxIncrementPixelReq req;
 
402
    XServerPtr  server = client->server;
 
403
 
 
404
    if (client->server->serverClient == client)
 
405
        return;
 
406
    req.reqType = server->lbxReq;
 
407
    req.lbxReqType = X_LbxIncrementPixel;
 
408
    req.length = 3;
 
409
    req.cmap = cmap;
 
410
    req.pixel = pixel;
 
411
    if (client->swapped) {
 
412
        SwapIncrementPixel(&req);
 
413
    }
 
414
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
415
}
 
416
 
 
417
void
 
418
#ifdef NeedFunctionPrototypes
 
419
SendAllocColor(
 
420
    ClientPtr   client,
 
421
    XID         cmap,
 
422
    CARD32      pixel,
 
423
    CARD16      red,
 
424
    CARD16      green,
 
425
    CARD16      blue)
 
426
#else
 
427
SendAllocColor(client, cmap, pixel, red, green, blue)
 
428
    ClientPtr   client;
 
429
    XID         cmap;
 
430
    CARD32      pixel;
 
431
    CARD16      red, green, blue;
 
432
#endif
 
433
{
 
434
    xLbxAllocColorReq req;
 
435
 
 
436
    req.reqType = client->server->lbxReq;
 
437
    req.lbxReqType = X_LbxAllocColor;
 
438
    req.length = sz_xLbxAllocColorReq >> 2;
 
439
    req.cmap = cmap;
 
440
    req.pixel = pixel;
 
441
    req.red = red;
 
442
    req.green = green;
 
443
    req.blue = blue;
 
444
    req.pad = 0;
 
445
 
 
446
    if (client->swapped)
 
447
        SwapAllocColor (&req);
 
448
 
 
449
    WriteReqToServer (client, sizeof(req), (char *) &req, TRUE);
 
450
}
 
451
 
 
452
void
 
453
SendGetModifierMapping(client)
 
454
    ClientPtr   client;
 
455
{
 
456
    xLbxGetModifierMappingReq req;
 
457
    XServerPtr  server = client->server;
 
458
 
 
459
    if (client->server->serverClient == client)
 
460
        return;
 
461
 
 
462
    req.reqType = server->lbxReq;
 
463
    req.lbxReqType = X_LbxGetModifierMapping;
 
464
    req.length = 1;
 
465
    if (client->swapped) {
 
466
        SwapGetModifierMapping(&req);
 
467
    }
 
468
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
469
}
 
470
 
 
471
void
 
472
SendGetKeyboardMapping(client)
 
473
    ClientPtr   client;
 
474
{
 
475
    xLbxGetKeyboardMappingReq req;
 
476
    XServerPtr  server = client->server;
 
477
 
 
478
    if (client->server->serverClient == client)
 
479
        return;
 
480
 
 
481
    /*
 
482
     * always ask for entire thing so tag always works, and pass on requested
 
483
     * subset
 
484
     */
 
485
    req.reqType = server->lbxReq;
 
486
    req.lbxReqType = X_LbxGetKeyboardMapping;
 
487
    req.length = 2;
 
488
    req.firstKeyCode = LBXMinKeyCode(client);
 
489
    req.count = LBXMaxKeyCode(client) - LBXMinKeyCode(client) + 1;
 
490
    req.pad1 = 0;
 
491
    if (client->swapped) {
 
492
        SwapGetKeyboardMapping(&req);
 
493
    }
 
494
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
495
}
 
496
 
 
497
void
 
498
SendQueryFont(client, fid)
 
499
    ClientPtr   client;
 
500
    XID         fid;
 
501
{
 
502
    xLbxQueryFontReq req;
 
503
    XServerPtr  server = client->server;
 
504
 
 
505
    if (client->server->serverClient == client)
 
506
        return;
 
507
 
 
508
    req.reqType = server->lbxReq;
 
509
    req.lbxReqType = X_LbxQueryFont;
 
510
    req.length = 2;
 
511
    req.fid = fid;
 
512
    if (client->swapped) {
 
513
        SwapQueryFont(&req);
 
514
    }
 
515
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
516
}
 
517
 
 
518
void
 
519
SendChangeProperty(client, win, prop, type, format, mode, num)
 
520
    ClientPtr   client;
 
521
    Window      win;
 
522
    Atom        prop,
 
523
                type;
 
524
    int         format,
 
525
                mode;
 
526
    unsigned long num;
 
527
{
 
528
    xLbxChangePropertyReq req;
 
529
    XServerPtr  server = client->server;
 
530
 
 
531
    if (client->server->serverClient == client)
 
532
        return;
 
533
 
 
534
    req.reqType = server->lbxReq;
 
535
    req.lbxReqType = X_LbxChangeProperty;
 
536
    req.length = 6;
 
537
    req.window = win;
 
538
    req.property = prop;
 
539
    req.type = type;
 
540
    req.format = format;
 
541
    req.mode = mode;
 
542
    req.nUnits = num;
 
543
    req.pad[0] = req.pad[1] = 0;
 
544
    if (client->swapped) {
 
545
        SwapChangeProperty(&req);
 
546
    }
 
547
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
548
}
 
549
 
 
550
void
 
551
SendGetProperty(client, win, prop, type, delete, off, len)
 
552
    ClientPtr   client;
 
553
    Window      win;
 
554
    Atom        prop,
 
555
                type;
 
556
    Bool        delete;
 
557
    unsigned long off,
 
558
                len;
 
559
{
 
560
    xLbxGetPropertyReq req;
 
561
    XServerPtr  server = client->server;
 
562
 
 
563
    if (client->server->serverClient == client)
 
564
        return;
 
565
 
 
566
    req.reqType = server->lbxReq;
 
567
    req.lbxReqType = X_LbxGetProperty;
 
568
    req.length = 7;
 
569
    req.window = win;
 
570
    req.property = prop;
 
571
    req.type = type;
 
572
    req.delete = delete;
 
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);
 
578
    }
 
579
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
580
}
 
581
 
 
582
void
 
583
SendInvalidateTag(client, tag)
 
584
    ClientPtr   client;
 
585
    XID         tag;
 
586
{
 
587
    xLbxInvalidateTagReq req;
 
588
    XServerPtr  server;
 
589
 
 
590
    if (!servers[0])            /* proxy resetting */
 
591
        return;
 
592
 
 
593
    server = client->server;
 
594
 
 
595
    req.reqType = server->lbxReq;
 
596
    req.lbxReqType = X_LbxInvalidateTag;
 
597
    req.length = 2;
 
598
    req.tag = tag;
 
599
    /* need tag type ? */
 
600
    if (client->swapped) {
 
601
        SwapInvalidateTag(&req);
 
602
    }
 
603
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
604
}
 
605
 
 
606
void
 
607
SendTagData(client, tag, len, data)
 
608
    ClientPtr   client;
 
609
    XID         tag;
 
610
    unsigned long len;
 
611
    pointer     data;
 
612
{
 
613
    xLbxTagDataReq req,
 
614
               *reqp;
 
615
    int         req_len;
 
616
    XServerPtr  server;
 
617
 
 
618
    server = client->server;
 
619
 
 
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);
 
624
    } else {
 
625
        reqp = &req;
 
626
    }
 
627
    reqp->reqType = server->lbxReq;
 
628
    reqp->lbxReqType = X_LbxTagData;
 
629
    reqp->length = req_len;
 
630
    reqp->real_length = len;
 
631
    reqp->tag = tag;
 
632
    /* need tag type ? */
 
633
    if (reqp == &req) {
 
634
        WriteToServer(server->serverClient, 
 
635
                      sizeof(req), (char *) &req, TRUE, FALSE);
 
636
        if (len)
 
637
            WriteToServer(server->serverClient, 
 
638
                          len, (char *) data, FALSE, FALSE);
 
639
    } else {
 
640
        WriteReqToServer(server->serverClient, 
 
641
                         req_len << 2, (char *) reqp, FALSE);
 
642
        xfree(reqp);
 
643
    }
 
644
}
 
645
 
 
646
void
 
647
SendGetImage(client, drawable, x, y, width, height, planeMask, format)
 
648
    ClientPtr   client;
 
649
    Drawable    drawable;
 
650
    int         x;
 
651
    int         y;
 
652
    unsigned int width;
 
653
    unsigned int height;
 
654
    unsigned long planeMask;
 
655
    int         format;
 
656
{
 
657
    xLbxGetImageReq req;
 
658
    XServerPtr  server = client->server;
 
659
 
 
660
    if (client->server->serverClient == client)
 
661
        return;
 
662
 
 
663
    req.reqType = server->lbxReq;
 
664
    req.lbxReqType = X_LbxGetImage;
 
665
    req.length = 6;
 
666
    req.drawable = drawable;
 
667
    req.x = x;
 
668
    req.y = y;
 
669
    req.width = width;
 
670
    req.height = height;
 
671
    req.planeMask = planeMask;
 
672
    req.format = format;
 
673
    req.pad1 = 0;
 
674
    req.pad2 = 0;
 
675
 
 
676
    if (client->swapped) {
 
677
        SwapGetImage(&req);
 
678
    }
 
679
    WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
 
680
}
 
681
 
 
682
static Bool
 
683
SendInternAtoms (server)
 
684
    XServerPtr server;
 
685
{
 
686
    xLbxInternAtomsReq *req;
 
687
    int reqSize, i, num;
 
688
    char lenbuf[2];
 
689
    char *ptr;
 
690
 
 
691
    reqSize = sz_xLbxInternAtomsReq;
 
692
    num = 0;
 
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);
 
696
            num++;
 
697
        }
 
698
    }
 
699
    if (!num)
 
700
        return FALSE;
 
701
 
 
702
    if (!(req = (xLbxInternAtomsReq *) xalloc (reqSize)))
 
703
        return FALSE;
 
704
 
 
705
    req->reqType = server->lbxReq;
 
706
    req->lbxReqType = X_LbxInternAtoms;
 
707
    req->length = (reqSize + 3) >> 2;
 
708
    req->num = num;
 
709
 
 
710
    ptr = (char *) req + sz_xLbxInternAtomsReq;
 
711
 
 
712
    for (i = 0; i < server->atom_control_count; i++)
 
713
    {
 
714
        if (server->atom_control[i].flags & AtomPreInternFlag) {
 
715
            *((CARD16 *) lenbuf) = server->atom_control[i].len;
 
716
            ptr[0] = lenbuf[0];
 
717
            ptr[1] = lenbuf[1];
 
718
            ptr += 2;
 
719
            memcpy (ptr, 
 
720
                    server->atom_control[i].name, 
 
721
                    server->atom_control[i].len);
 
722
            ptr += server->atom_control[i].len;
 
723
        }
 
724
    }
 
725
 
 
726
    WriteToClient(server->serverClient, reqSize, (char *) req);
 
727
 
 
728
    xfree (req);
 
729
    return TRUE;
 
730
}
 
731
 
 
732
/*ARGSUSED*/
 
733
static void
 
734
InternAtomsReply (server, rep)
 
735
    XServerPtr  server;
 
736
    xLbxInternAtomsReply *rep;
 
737
{
 
738
    Atom *atoms = (Atom *) ((char *) rep + sz_xLbxInternAtomsReplyHdr);
 
739
    int i;
 
740
 
 
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,
 
746
                                *atoms++, TRUE);
 
747
    }
 
748
 
 
749
    SendInitLBXPackets(server);
 
750
 
 
751
    /*
 
752
     * Now the proxy is ready to accept connections from clients.
 
753
     */
 
754
 
 
755
    (void) ListenWellKnownSockets ();
 
756
}
 
757
 
 
758
 
 
759
static unsigned long pendingServerReplySequence;
 
760
static void (*serverReplyFunc) ();
 
761
 
 
762
static void
 
763
ServerReply(server, rep)
 
764
    XServerPtr  server;
 
765
    xReply     *rep;
 
766
{
 
767
    if (serverReplyFunc &&
 
768
            rep->generic.sequenceNumber == pendingServerReplySequence) {
 
769
        /*
 
770
         * We got the reply we were waiting from the server
 
771
         */
 
772
 
 
773
        (*serverReplyFunc) (server, rep);
 
774
 
 
775
        /*
 
776
         * ExpectServerReply() might have been called within the server
 
777
         * reply func just processed.
 
778
         */
 
779
 
 
780
        if (rep->generic.sequenceNumber == pendingServerReplySequence)
 
781
            serverReplyFunc = 0;
 
782
    }
 
783
}
 
784
 
 
785
static void
 
786
ExpectServerReply(server, func)
 
787
    XServerPtr  server;
 
788
    void        (*func) ();
 
789
{
 
790
    pendingServerReplySequence = server->serverClient->sequence;
 
791
    serverReplyFunc = func;
 
792
}
 
793
 
 
794
extern int  (*ServerVector[]) ();
 
795
 
 
796
static unsigned long
 
797
ServerRequestLength(req, sc, gotnow, partp)
 
798
    xReq       *req;
 
799
    ClientPtr   sc;
 
800
    int         gotnow;
 
801
    Bool       *partp;
 
802
{
 
803
    XServerPtr  server = servers[sc->lbxIndex];
 
804
    ClientPtr   client = server->recv;
 
805
    xReply     *rep;
 
806
    xConnSetupPrefix *pre;
 
807
 
 
808
    if (!req)
 
809
        req = (xReq *) sc->requestBuffer;
 
810
    if (gotnow < sizeof(xReq)) {
 
811
        *partp = TRUE;
 
812
        return sizeof(xReq);
 
813
    }
 
814
    if (req->reqType == server->lbxEvent && req->data == LbxDeltaEvent) {
 
815
        *partp = FALSE;
 
816
        return req->length << 2;
 
817
    }
 
818
    if (req->reqType == server->lbxEvent && req->data == LbxSwitchEvent) {
 
819
        *partp = FALSE;
 
820
        return sz_xLbxSwitchEvent;
 
821
    }
 
822
    if (req->reqType == server->lbxEvent + LbxQuickMotionDeltaEvent) {
 
823
        *partp = FALSE;
 
824
        return sz_lbxQuickMotionDeltaEvent;
 
825
    }
 
826
    if (req->reqType == server->lbxEvent && req->data == LbxMotionDeltaEvent) {
 
827
        *partp = FALSE;
 
828
        return sz_lbxMotionDeltaEvent;
 
829
    }
 
830
    if (client->awaitingSetup) {
 
831
        if (gotnow < 8) {
 
832
            *partp = TRUE;
 
833
            return 8;
 
834
        }
 
835
        pre = (xConnSetupPrefix *) req;
 
836
        *partp = FALSE;
 
837
        return 8 + (pre->length << 2);
 
838
    }
 
839
    if (gotnow < 8) {
 
840
        *partp = TRUE;
 
841
        return 8;
 
842
    }
 
843
    *partp = FALSE;
 
844
    rep = (xReply *) req;
 
845
    if (rep->generic.type != X_Reply) {
 
846
        return EventLength((xEvent *)rep, server->lbxNegOpt.squish);
 
847
    }
 
848
    return sz_xReply + (rep->generic.length << 2);
 
849
}
 
850
 
 
851
int
 
852
ServerProcStandardEvent(sc)
 
853
    ClientPtr   sc;
 
854
{
 
855
    xReply     *rep;
 
856
    XServerPtr  server = servers[sc->lbxIndex];
 
857
    ClientPtr   client = server->recv;
 
858
    int         len;
 
859
    Bool        part;
 
860
    Bool        cacheable = (server->initialized) ? TRUE : FALSE;
 
861
 
 
862
    rep = (xReply *) sc->requestBuffer;
 
863
 
 
864
    /* need to calculate length up from for Delta cache */
 
865
    len = RequestLength(rep, sc, 8, &part);
 
866
 
 
867
#ifdef LBX_STATS
 
868
    delta_in_total++;
 
869
#endif
 
870
 
 
871
    if (rep->generic.type == server->lbxEvent &&
 
872
            rep->generic.data1 == LbxDeltaEvent) {
 
873
        xLbxDeltaReq *delta = (xLbxDeltaReq *) rep;
 
874
 
 
875
#ifdef LBX_STATS
 
876
        delta_in_attempts++;
 
877
        delta_in_hits++;
 
878
#endif
 
879
 
 
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);
 
885
 
 
886
        /* Make local copy in case someone writes to the request buffer */
 
887
        memcpy(server->tempdeltabuf, (char *) rep, len);
 
888
        rep = (xReply *) server->tempdeltabuf;
 
889
 
 
890
        cacheable = FALSE;
 
891
    }
 
892
 
 
893
    /* stick in delta buffer before LBX code modified things */
 
894
    if (cacheable && DELTA_CACHEABLE(&server->indeltas, len)) {
 
895
 
 
896
#ifdef LBX_STATS
 
897
        delta_in_attempts++;
 
898
#endif
 
899
 
 
900
        LBXAddDeltaIn(&server->indeltas, (unsigned char *) rep, len);
 
901
    }
 
902
    if (rep->generic.type == server->lbxEvent &&
 
903
        rep->generic.data1 != LbxMotionDeltaEvent) {
 
904
        switch (rep->generic.data1) {
 
905
        case LbxSwitchEvent:
 
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);
 
911
            break;
 
912
        case LbxCloseEvent:
 
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);
 
918
            break;
 
919
        case LbxInvalidateTagEvent:
 
920
            DBG(DBG_CLIENT, (stderr, "invalidate tag %d type %d\n",
 
921
                             ((xLbxInvalidateTagEvent *)rep)->tag,
 
922
                             ((xLbxInvalidateTagEvent *)rep)->tagType));
 
923
            LbxFreeTag(server,
 
924
                       ((xLbxInvalidateTagEvent *)rep)->tag,
 
925
                       ((xLbxInvalidateTagEvent *)rep)->tagType);
 
926
            break;
 
927
        case LbxSendTagDataEvent:
 
928
            DBG(DBG_CLIENT, (stderr, "send tag data %d type %d\n",
 
929
                             ((xLbxSendTagDataEvent *)rep)->tag,
 
930
                             ((xLbxSendTagDataEvent *)rep)->tagType));
 
931
            LbxSendTagData(sc,
 
932
                           ((xLbxSendTagDataEvent *)rep)->tag,
 
933
                           ((xLbxSendTagDataEvent *)rep)->tagType);
 
934
            break;
 
935
        case LbxListenToOne:
 
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);
 
940
            else
 
941
                LbxOnlyListenToOneClient(clients[((xLbxListenToOneEvent *)rep)->client]);
 
942
            break;
 
943
        case LbxListenToAll:
 
944
            DBG(DBG_CLIENT, (stderr, "listen to all clients\n"));
 
945
            LbxListenToAllClients(server);
 
946
            break;
 
947
        case LbxReleaseCmapEvent:
 
948
        {
 
949
            Colormap cmap = ((xLbxReleaseCmapEvent *)rep)->colormap;
 
950
            ColormapPtr pmap;
 
951
 
 
952
            pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
 
953
#ifdef COLOR_DEBUG
 
954
            fprintf (stderr, "\nGot LbxReleaseCmapEvent, cmap = 0x%x\n\n", cmap);
 
955
#endif
 
956
            if (pmap && pmap->grab_status == CMAP_GRABBED)
 
957
                ReleaseCmap (client, pmap);
 
958
            break;
 
959
        }
 
960
        case LbxFreeCellsEvent:
 
961
        {
 
962
            Colormap cmap = ((xLbxFreeCellsEvent *)rep)->colormap;
 
963
            Pixel start = ((xLbxFreeCellsEvent *)rep)->pixelStart;
 
964
            Pixel end = ((xLbxFreeCellsEvent *)rep)->pixelEnd;
 
965
            ColormapPtr pmap;
 
966
 
 
967
            pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
 
968
#ifdef COLOR_DEBUG
 
969
            fprintf (stderr, "\nGot LbxFreeCellsEvent, cmap = 0x%x, ", cmap);
 
970
            fprintf (stderr, "startPixel = %d, endPixel = %d\n\n",
 
971
                     start, end);
 
972
#endif
 
973
            if (pmap && pmap->grab_status == CMAP_GRABBED)
 
974
                GotServerFreeCellsEvent (pmap, start, end);
 
975
            break;
 
976
        }
 
977
        }
 
978
    } else if ((rep->generic.type == server->lbxEvent &&
 
979
                rep->generic.data1 == LbxMotionDeltaEvent) ||
 
980
               (rep->generic.type == server->lbxEvent + LbxQuickMotionDeltaEvent))
 
981
    {
 
982
        lbxMotionCache *motionCache = &server->motionCache;
 
983
 
 
984
        /*
 
985
         * We use the motion delta event to generate a real MotionNotify event.
 
986
         *
 
987
         * The motion cache contains the last motion event we got from
 
988
         * the server.
 
989
         *
 
990
         * The following are always stored in the cache in the proxy's
 
991
         * byte order:
 
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.
 
995
         *
 
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
 
1003
         * fields.
 
1004
         */
 
1005
 
 
1006
        AllowMotion(client, 1);
 
1007
 
 
1008
        if (rep->generic.type == server->lbxEvent)
 
1009
        {
 
1010
            lbxMotionDeltaEvent *mev = (lbxMotionDeltaEvent *) rep;
 
1011
 
 
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;
 
1018
        }
 
1019
        else
 
1020
        {
 
1021
            lbxQuickMotionDeltaEvent *qmev = (lbxQuickMotionDeltaEvent *) rep;
 
1022
 
 
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;
 
1028
        }
 
1029
 
 
1030
        if (!client->clientGone) {
 
1031
            xEvent ev;
 
1032
            int n;
 
1033
 
 
1034
            if (motionCache->swapped != client->swapped)
 
1035
            {
 
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;
 
1041
            }
 
1042
 
 
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;
 
1056
 
 
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);
 
1064
            }
 
1065
            /*
 
1066
             * Write the reply
 
1067
             */
 
1068
 
 
1069
            DoLBXReply (client, (char *) &ev, sz_xEvent);
 
1070
        }
 
1071
 
 
1072
    } else {
 
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);
 
1077
        } else {
 
1078
            xEvent      ev;
 
1079
            char       *rp;
 
1080
            int         n;
 
1081
 
 
1082
            if (!client->awaitingSetup && UnsquishEvent(rep, &ev, &len))
 
1083
                rp = (char *) &ev;
 
1084
            else
 
1085
                rp = (char *) rep;
 
1086
 
 
1087
            if (rep->generic.type == MotionNotify) {
 
1088
                xEvent *mev = (xEvent *) rp;
 
1089
                lbxMotionCache *motionCache = &server->motionCache;
 
1090
 
 
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)
 
1106
                {
 
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);
 
1113
                }
 
1114
            }
 
1115
 
 
1116
            /*
 
1117
             * Write the reply
 
1118
             */
 
1119
 
 
1120
            if (!client->clientGone)
 
1121
                DoLBXReply (client, rp, len);
 
1122
            client->awaitingSetup = FALSE;
 
1123
        }
 
1124
    }
 
1125
 
 
1126
    return Success;
 
1127
}
 
1128
 
 
1129
static void
 
1130
LbxIgnoreAllClients(server)
 
1131
    XServerPtr  server;
 
1132
{
 
1133
    if (!server->lbxIgnoringAll) {
 
1134
        if (GrabInProgress) {
 
1135
            server->lbxGrabInProgress = GrabInProgress;
 
1136
            ListenToAllClients();
 
1137
        }
 
1138
        OnlyListenToOneClient(server->serverClient);
 
1139
        server->lbxIgnoringAll = TRUE;
 
1140
    }
 
1141
}
 
1142
 
 
1143
/* ARGSUSED */
 
1144
static void
 
1145
LbxAttendAllClients(server)
 
1146
    XServerPtr  server;
 
1147
{
 
1148
    if (server->lbxIgnoringAll) {
 
1149
        ListenToAllClients();
 
1150
        server->lbxIgnoringAll = FALSE;
 
1151
        if (server->lbxGrabInProgress) {
 
1152
            OnlyListenToOneClient(clients[server->lbxGrabInProgress]);
 
1153
            server->lbxGrabInProgress = 0;
 
1154
        }
 
1155
    }
 
1156
}
 
1157
 
 
1158
/* ARGSUSED */
 
1159
static void
 
1160
LbxOnlyListenToOneClient(client)
 
1161
    ClientPtr   client;
 
1162
{
 
1163
    /*
 
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
 
1166
     * different server.
 
1167
     */
 
1168
    return;
 
1169
}
 
1170
 
 
1171
/* ARGSUSED */
 
1172
static void
 
1173
LbxListenToAllClients(server)
 
1174
    XServerPtr server;
 
1175
{
 
1176
    /*
 
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
 
1179
     * different server.
 
1180
     */
 
1181
    return;
 
1182
}
 
1183
 
 
1184
/* ARGSUSED */
 
1185
static Bool
 
1186
ProxyWorkProc(dummy, index)
 
1187
    pointer     dummy;
 
1188
    int         index;
 
1189
{
 
1190
    XServerPtr  server;
 
1191
    xLbxAllowMotionReq req;
 
1192
 
 
1193
    if ((server = servers[index]) == 0)
 
1194
        return TRUE;
 
1195
    if (!server->initialized)
 
1196
        return TRUE;
 
1197
 
 
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;
 
1203
        req.length = 2;
 
1204
        req.num = server->motion_allowed;
 
1205
        server->motion_allowed = 0;
 
1206
        WriteToClient(server->serverClient, sizeof(req), &req);
 
1207
    }
 
1208
    /* Need to flush the output buffers before we flush compression buffer */
 
1209
    if (NewOutputPending)
 
1210
        FlushAllOutput();
 
1211
 
 
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);
 
1217
    }
 
1218
    /*
 
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.
 
1221
     */
 
1222
    if (PendingClientOutput(server->serverClient))
 
1223
        LbxIgnoreAllClients(server);
 
1224
    else
 
1225
        LbxAttendAllClients(server);
 
1226
 
 
1227
    return FALSE;
 
1228
}
 
1229
 
 
1230
Bool reconnectAfterCloseServer = FALSE;
 
1231
 
 
1232
void
 
1233
CloseServer(client)
 
1234
    ClientPtr   client; /* This client is connected to a display server */
 
1235
{
 
1236
    XServerPtr  server;
 
1237
    int         i;
 
1238
    int         found;
 
1239
 
 
1240
    DBG(DBG_CLOSE, (stderr, "closing down server\n"));
 
1241
 
 
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);
 
1248
 
 
1249
    /*
 
1250
     * If another server is still active, don't terminate
 
1251
     */
 
1252
    for (found = 0, i = 0; i < lbxMaxServers; i++) {
 
1253
        if (servers[i]) {
 
1254
            found = 1;
 
1255
            break;
 
1256
        }
 
1257
    }
 
1258
    if (!found && !reconnectAfterCloseServer)
 
1259
        dispatchException |= DE_TERMINATE;
 
1260
 
 
1261
    /*
 
1262
     * Close all of the "real" clients for this server
 
1263
     */
 
1264
    for (i = 1; i < currentMaxClients; i++) {
 
1265
       if (clients[i] && 
 
1266
           clients[i] != client && 
 
1267
           clients[i]->server == server) {          
 
1268
 
 
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;
 
1276
            xfree (clients[i]);
 
1277
            --nClients;
 
1278
            while (!clients[currentMaxClients-1])
 
1279
                currentMaxClients--;
 
1280
        }
 
1281
    }
 
1282
 
 
1283
    /*
 
1284
     * Need to remove this server's listen port(s)
 
1285
     */
 
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);
 
1291
        }
 
1292
 
 
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;
 
1297
    }
 
1298
 
 
1299
    /*
 
1300
     * Try to reconnect to this server
 
1301
     */
 
1302
    if (reconnectAfterCloseServer && !ConnectToServer (server->display_name)) {
 
1303
 
 
1304
        fprintf (stderr, "could not reconnect to '%s'\n", server->display_name);
 
1305
 
 
1306
        if (!found && !proxyMngr)
 
1307
            /* 
 
1308
             * There is no need to continue if there is no proxyManager
 
1309
             */
 
1310
            dispatchException |= DE_TERMINATE;
 
1311
    }
 
1312
 
 
1313
    if (server->display_name)
 
1314
        free (server->display_name);
 
1315
    if (server->proxy_name)
 
1316
        free (server->proxy_name);
 
1317
    xfree (server->requestVector);
 
1318
    xfree(server);
 
1319
 
 
1320
    CloseDownFileDescriptor(client);
 
1321
 
 
1322
    isItTimeToYield = 1;
 
1323
}
 
1324
 
 
1325
 
 
1326
static void
 
1327
StartProxyReply(server, rep)
 
1328
    XServerPtr  server;
 
1329
    xLbxStartReply *rep;
 
1330
{
 
1331
    int         replylen;
 
1332
 
 
1333
    replylen = (rep->length << 2) + sz_xLbxStartReply - sz_xLbxStartReplyHdr;
 
1334
    if (rep->nOpts == 0xff) {
 
1335
        fprintf(stderr, "WARNING: option negotiation failed - using defaults\n");
 
1336
        LbxOptInit(server);
 
1337
    } else if (LbxOptParseReply(server, rep->nOpts,
 
1338
                        (unsigned char *)&rep->optDataStart, replylen) < 0) {
 
1339
        FatalError("Bad options from server");
 
1340
    }
 
1341
 
 
1342
#ifdef OPTDEBUG
 
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);
 
1346
#endif
 
1347
 
 
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);
 
1353
 
 
1354
#ifdef OPTDEBUG
 
1355
    fprintf(stderr, "squishing = %d\n", server->lbxNegOpt.squish);
 
1356
    fprintf(stderr, "useTags = %d\n", server->lbxNegOpt.useTags);
 
1357
#endif
 
1358
 
 
1359
    TagsInit(server, server->lbxNegOpt.useTags);
 
1360
 
 
1361
    if (!server->lbxNegOpt.useTags)
 
1362
    {
 
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;
 
1368
    }
 
1369
 
 
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);
 
1374
 
 
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);
 
1381
        extra += len;
 
1382
        server->lbxNegOpt.streamOpts.streamCompStuffInput(server->fd, 
 
1383
                                                          extra, 
 
1384
                                                          left);
 
1385
        SkipInClientBuffer(server->serverClient, left + len, 0);
 
1386
        StartOutputCompression(server->serverClient,
 
1387
            server->lbxNegOpt.streamOpts.streamCompOn,
 
1388
            server->lbxNegOpt.streamOpts.streamCompOff);
 
1389
    }
 
1390
    server->initialized = TRUE;
 
1391
    MakeClientGrabImpervious(server->serverClient);
 
1392
 
 
1393
    if (SendInternAtoms(server))
 
1394
        ExpectServerReply (server, InternAtomsReply);
 
1395
    else
 
1396
    {
 
1397
        SendInitLBXPackets(server);
 
1398
 
 
1399
        /*
 
1400
         * Now the proxy is ready to accept connections from clients.
 
1401
         */
 
1402
 
 
1403
        (void) ListenWellKnownSockets ();
 
1404
    }
 
1405
}
 
1406
 
 
1407
static void
 
1408
StartProxy(server)
 
1409
    XServerPtr  server;
 
1410
{
 
1411
    char        buf[1024];
 
1412
    int         reqlen;
 
1413
    xLbxStartProxyReq *n = (xLbxStartProxyReq *) buf;
 
1414
 
 
1415
    LbxOptInit(server);
 
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;
 
1421
    /*
 
1422
     * Don't call WriteToServer because we don't want to switch.
 
1423
     */
 
1424
    WriteToClient(server->serverClient, n->length << 2, (char *) n);
 
1425
    server->serverClient->sequence++;
 
1426
    ExpectServerReply(server, StartProxyReply);
 
1427
    while (NewOutputPending)
 
1428
        FlushAllOutput();
 
1429
}
 
1430
 
 
1431
static Bool
 
1432
InitServer (dpy_name, i, server, sequencep)
 
1433
    char*       dpy_name;
 
1434
    int         i;
 
1435
    XServerPtr  server;
 
1436
    int*        sequencep;
 
1437
{
 
1438
    server->index = i;
 
1439
 
 
1440
    DBG(DBG_IO, (stderr, "making server connection\n"));
 
1441
    server->dpy = DisplayOpen (dpy_name, 
 
1442
                               &server->lbxReq, 
 
1443
                               &server->lbxEvent, 
 
1444
                               &server->lbxError, 
 
1445
                               sequencep);
 
1446
    if (!server->dpy) return FALSE;
 
1447
 
 
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;
 
1457
 
 
1458
    /*
 
1459
     * Initialize the atom fields
 
1460
     */
 
1461
    server->atom_control_count = 0;
 
1462
    server->atom_control = NULL;
 
1463
    LBXReadAtomsFile(server);
 
1464
 
 
1465
    /*
 
1466
     * Initialize global and property caches
 
1467
     */
 
1468
    server->num_caches = 0;
 
1469
    server->seed = 0;
 
1470
 
 
1471
    /*
 
1472
     * The ProcVector table contains the default functions plus any
 
1473
     * changes that were made when the command line options were
 
1474
     * parsed.
 
1475
     *
 
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.
 
1480
     *
 
1481
     * When a client connects, its requestVector will be set to its
 
1482
     * server's requestVector.
 
1483
     */
 
1484
    server->requestVector = (int (**)()) xalloc (sizeof (ProcVector));
 
1485
    if (!server->requestVector) return FALSE;
 
1486
    memcpy (server->requestVector, ProcVector, sizeof (ProcVector));
 
1487
 
 
1488
    /*
 
1489
     * Initialize the resource fields
 
1490
     */
 
1491
    server->lastLbxClientIndexLookup = NULL;
 
1492
 
 
1493
    /*
 
1494
     * Initialize the grab state variables
 
1495
     */
 
1496
    server->lbxIgnoringAll = 0;
 
1497
    server->lbxGrabInProgress = 0;
 
1498
 
 
1499
    return TRUE;
 
1500
}
 
1501
 
 
1502
Bool
 
1503
ConnectToServer(dpy_name)
 
1504
    char       *dpy_name;
 
1505
{
 
1506
    int         i, j;
 
1507
    XServerPtr  server;
 
1508
    int         sequence;
 
1509
    ClientPtr   sc;
 
1510
    static int  been_there;
 
1511
    static char my_host[250];
 
1512
    char        proxy_address[250+6];
 
1513
 
 
1514
#ifdef NEED_UTSNAME
 
1515
    struct utsname name;
 
1516
#endif
 
1517
 
 
1518
    for (i = 0; i < lbxMaxServers; i++)
 
1519
        if (!servers[i])
 
1520
            break;
 
1521
    if (i == lbxMaxServers) {
 
1522
        if (proxyMngr)
 
1523
            SendGetProxyAddrReply( PM_iceConn, PM_Unable, NULL,
 
1524
                                   "too many servers" );
 
1525
        return FALSE;
 
1526
    }
 
1527
    server = (XServerPtr) xalloc(sizeof(XServerRec));
 
1528
    if (!server) {
 
1529
        if (proxyMngr)
 
1530
            SendGetProxyAddrReply( PM_iceConn, PM_Unable, NULL,
 
1531
                                   "memory allocation failure");
 
1532
        return FALSE;
 
1533
    }
 
1534
    bzero(server, sizeof(XServerRec));
 
1535
    
 
1536
    if (!InitServer (dpy_name, i, server, &sequence)) {
 
1537
        if (proxyMngr) {
 
1538
            (void) snprintf (proxy_address, sizeof(proxy_address),
 
1539
                            "could not connect to server '%s'",
 
1540
                            dpy_name);
 
1541
            SendGetProxyAddrReply( PM_iceConn, PM_Failure, NULL, proxy_address);
 
1542
        }
 
1543
        xfree(server);
 
1544
        return FALSE;
 
1545
    }
 
1546
 
 
1547
    /*
 
1548
     * Create the socket(s) this display will listen on
 
1549
     */
 
1550
    for (j=0; j < MAXTRANSPORTS; j++)
 
1551
        server->listen_fds[j] = -1;
 
1552
    CreateServerSockets(server->listen_fds);
 
1553
 
 
1554
    /*
 
1555
     * Generate the proxy address and save the host name part
 
1556
     */
 
1557
    if (!been_there || i == 0) {
 
1558
        been_there++;
 
1559
 
 
1560
        clients[0]->server = server;
 
1561
 
 
1562
#ifdef NEED_UTSNAME
 
1563
        uname (&name);
 
1564
        (void) snprintf(my_host,sizeof(my_host),"%s",name.nodename);
 
1565
#else
 
1566
        (void) gethostname (my_host,sizeof(my_host));
 
1567
#endif
 
1568
    }
 
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);
 
1574
        return FALSE;
 
1575
    }
 
1576
    
 
1577
    servers[i] = server;
 
1578
 
 
1579
    sc = AllocNewConnection(server->fd, -1, TRUE, NULL);
 
1580
    sc->server = server;
 
1581
    sc->public.requestLength = ServerRequestLength;
 
1582
    sc->lbxIndex = i;
 
1583
    sc->requestVector = ServerVector;
 
1584
    sc->awaitingSetup = FALSE;
 
1585
    sc->sequence = sequence;
 
1586
 
 
1587
    /*
 
1588
     * AllocNewConn didn't initialize the client resources so
 
1589
     * it needs to be done here
 
1590
     */
 
1591
    InitClientResources(sc);
 
1592
 
 
1593
    server->serverClient = sc;
 
1594
    server->proxy_name = strdup (proxy_address);
 
1595
    if (dpy_name)
 
1596
        server->display_name = strdup (dpy_name);
 
1597
 
 
1598
    StartProxy(server);
 
1599
 
 
1600
    if (proxyMngr) {
 
1601
        SendGetProxyAddrReply( PM_iceConn, PM_Success, proxy_address, NULL );
 
1602
    }
 
1603
 
 
1604
    return TRUE;
 
1605
}