tizen 2.4 release
[framework/uifw/xorg/server/xorg-server.git] / os / io.c
1 /***********************************************************
2
3 Copyright 1987, 1989, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27                         All Rights Reserved
28
29 Permission to use, copy, modify, and distribute this software and its 
30 documentation for any purpose and without fee is hereby granted, 
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in 
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.  
36
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
44
45 ******************************************************************/
46 /*****************************************************************
47  * i/o functions
48  *
49  *   WriteToClient, ReadRequestFromClient
50  *   InsertFakeRequest, ResetCurrentRequest
51  *
52  *****************************************************************/
53
54 #ifdef HAVE_DIX_CONFIG_H
55 #include <dix-config.h>
56 #endif
57
58 #undef DEBUG_COMMUNICATION
59
60 #ifdef WIN32
61 #include <X11/Xwinsock.h>
62 #endif
63 #include <stdio.h>
64 #define XSERV_t
65 #define TRANS_SERVER
66 #define TRANS_REOPEN
67 #include <X11/Xtrans/Xtrans.h>
68 #include <X11/Xmd.h>
69 #include <errno.h>
70 #if !defined(WIN32)
71 #include <sys/uio.h>
72 #endif
73 #include <X11/X.h>
74 #include <X11/Xproto.h>
75 #include "os.h"
76 #include "osdep.h"
77 #include <X11/Xpoll.h>
78 #include "opaque.h"
79 #include "dixstruct.h"
80 #include "misc.h"
81
82 CallbackListPtr ReplyCallback;
83 CallbackListPtr FlushCallback;
84
85 typedef struct _connectionInput {
86     struct _connectionInput *next;
87     char *buffer;               /* contains current client input */
88     char *bufptr;               /* pointer to current start of data */
89     int bufcnt;                 /* count of bytes in buffer */
90     int lenLastReq;
91     int size;
92     unsigned int ignoreBytes;   /* bytes to ignore before the next request */
93 } ConnectionInput;
94
95 typedef struct _connectionOutput {
96     struct _connectionOutput *next;
97     unsigned char *buf;
98     int size;
99     int count;
100 } ConnectionOutput;
101
102 static ConnectionInputPtr AllocateInputBuffer(void);
103 static ConnectionOutputPtr AllocateOutputBuffer(void);
104
105 /* If EAGAIN and EWOULDBLOCK are distinct errno values, then we check errno
106  * for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
107  * systems are broken and return EWOULDBLOCK when they should return EAGAIN
108  */
109 #ifndef WIN32
110 # if (EAGAIN != EWOULDBLOCK)
111 #  define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
112 # else
113 #  define ETEST(err) (err == EAGAIN)
114 # endif
115 #else   /* WIN32 The socket errorcodes differ from the normal errors */
116 #define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK)
117 #endif
118
119 static Bool CriticalOutputPending;
120 static int timesThisConnection = 0;
121 static ConnectionInputPtr FreeInputs = (ConnectionInputPtr) NULL;
122 static ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr) NULL;
123 static OsCommPtr AvailableInput = (OsCommPtr) NULL;
124
125 #define get_req_len(req,cli) ((cli)->swapped ? \
126                               lswaps((req)->length) : (req)->length)
127
128 #include <X11/extensions/bigreqsproto.h>
129
130 #define get_big_req_len(req,cli) ((cli)->swapped ? \
131                                   lswapl(((xBigReq *)(req))->length) : \
132                                   ((xBigReq *)(req))->length)
133
134 #define MAX_TIMES_PER         10
135 #define BUFSIZE 4096
136 #define BUFWATERMARK 8192
137
138 /*
139  *   A lot of the code in this file manipulates a ConnectionInputPtr:
140  *
141  *    -----------------------------------------------
142  *   |------- bufcnt ------->|           |           |
143  *   |           |- gotnow ->|           |           |
144  *   |           |-------- needed ------>|           |
145  *   |-----------+--------- size --------+---------->|
146  *    -----------------------------------------------
147  *   ^           ^
148  *   |           |
149  *   buffer   bufptr
150  *
151  *  buffer is a pointer to the start of the buffer.
152  *  bufptr points to the start of the current request.
153  *  bufcnt counts how many bytes are in the buffer.
154  *  size is the size of the buffer in bytes.
155  *
156  *  In several of the functions, gotnow and needed are local variables
157  *  that do the following:
158  *
159  *  gotnow is the number of bytes of the request that we're
160  *  trying to read that are currently in the buffer.
161  *  Typically, gotnow = (buffer + bufcnt) - bufptr
162  *
163  *  needed = the length of the request that we're trying to
164  *  read.  Watch out: needed sometimes counts bytes and sometimes
165  *  counts CARD32's.
166  */
167
168 /*****************************************************************
169  * ReadRequestFromClient
170  *    Returns one request in client->requestBuffer.  The request
171  *    length will be in client->req_len.  Return status is:
172  *
173  *    > 0  if  successful, specifies length in bytes of the request
174  *    = 0  if  entire request is not yet available
175  *    < 0  if  client should be terminated
176  *
177  *    The request returned must be contiguous so that it can be
178  *    cast in the dispatcher to the correct request type.  Because requests
179  *    are variable length, ReadRequestFromClient() must look at the first 4
180  *    or 8 bytes of a request to determine the length (the request length is
181  *    in the 3rd and 4th bytes of the request unless it is a Big Request
182  *    (see the Big Request Extension), in which case the 3rd and 4th bytes
183  *    are zero and the following 4 bytes are the request length.
184  *
185  *    Note: in order to make the server scheduler (WaitForSomething())
186  *    "fair", the ClientsWithInput mask is used.  This mask tells which
187  *    clients have FULL requests left in their buffers.  Clients with
188  *    partial requests require a read.  Basically, client buffers
189  *    are drained before select() is called again.  But, we can't keep
190  *    reading from a client that is sending buckets of data (or has
191  *    a partial request) because others clients need to be scheduled.
192  *****************************************************************/
193
194 static void
195 YieldControl(void)
196 {
197     isItTimeToYield = TRUE;
198     timesThisConnection = 0;
199 }
200
201 static void
202 YieldControlNoInput(int fd)
203 {
204     YieldControl();
205     FD_CLR(fd, &ClientsWithInput);
206 }
207
208 static void
209 YieldControlDeath(void)
210 {
211     timesThisConnection = 0;
212 }
213
214 /* If an input buffer was empty, either free it if it is too big or link it
215  * into our list of free input buffers.  This means that different clients can
216  * share the same input buffer (at different times).  This was done to save
217  * memory.
218  */
219 static void
220 NextAvailableInput(OsCommPtr oc)
221 {
222     if (AvailableInput) {
223         if (AvailableInput != oc) {
224             ConnectionInputPtr aci = AvailableInput->input;
225
226             if (aci->size > BUFWATERMARK) {
227                 free(aci->buffer);
228                 free(aci);
229             }
230             else {
231                 aci->next = FreeInputs;
232                 FreeInputs = aci;
233             }
234             AvailableInput->input = NULL;
235         }
236         AvailableInput = NULL;
237     }
238 }
239
240 int
241 ReadRequestFromClient(ClientPtr client)
242 {
243     OsCommPtr oc = (OsCommPtr) client->osPrivate;
244     ConnectionInputPtr oci = oc->input;
245     int fd = oc->fd;
246     unsigned int gotnow, needed;
247     int result;
248     register xReq *request;
249     Bool need_header;
250     Bool move_header;
251
252     NextAvailableInput(oc);
253
254     /* make sure we have an input buffer */
255
256     if (!oci) {
257         if ((oci = FreeInputs)) {
258             FreeInputs = oci->next;
259         }
260         else if (!(oci = AllocateInputBuffer())) {
261             YieldControlDeath();
262             return -1;
263         }
264         oc->input = oci;
265     }
266
267 #if XTRANS_SEND_FDS
268     /* Discard any unused file descriptors */
269     while (client->req_fds > 0) {
270         int req_fd = ReadFdFromClient(client);
271         if (req_fd >= 0)
272             close(req_fd);
273     }
274 #endif
275     /* advance to start of next request */
276
277     oci->bufptr += oci->lenLastReq;
278
279     need_header = FALSE;
280     move_header = FALSE;
281     gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
282
283     if (oci->ignoreBytes > 0) {
284         if (oci->ignoreBytes > oci->size)
285             needed = oci->size;
286         else
287             needed = oci->ignoreBytes;
288     }
289     else if (gotnow < sizeof(xReq)) {
290         /* We don't have an entire xReq yet.  Can't tell how big
291          * the request will be until we get the whole xReq.
292          */
293         needed = sizeof(xReq);
294         need_header = TRUE;
295     }
296     else {
297         /* We have a whole xReq.  We can tell how big the whole
298          * request will be unless it is a Big Request.
299          */
300         request = (xReq *) oci->bufptr;
301         needed = get_req_len(request, client);
302         if (!needed && client->big_requests) {
303             /* It's a Big Request. */
304             move_header = TRUE;
305             if (gotnow < sizeof(xBigReq)) {
306                 /* Still need more data to tell just how big. */
307                 needed = bytes_to_int32(sizeof(xBigReq));       /* needed is in CARD32s now */
308                 need_header = TRUE;
309             }
310             else
311                 needed = get_big_req_len(request, client);
312         }
313         client->req_len = needed;
314         needed <<= 2;           /* needed is in bytes now */
315     }
316     if (gotnow < needed) {
317         /* Need to read more data, either so that we can get a
318          * complete xReq (if need_header is TRUE), a complete
319          * xBigReq (if move_header is TRUE), or the rest of the
320          * request (if need_header and move_header are both FALSE).
321          */
322
323         oci->lenLastReq = 0;
324         if (needed > maxBigRequestSize << 2) {
325             /* request is too big for us to handle */
326             /*
327              * Mark the rest of it as needing to be ignored, and then return
328              * the full size.  Dispatch() will turn it into a BadLength error.
329              */
330             oci->ignoreBytes = needed - gotnow;
331             oci->lenLastReq = gotnow;
332             return needed;
333         }
334         if ((gotnow == 0) || ((oci->bufptr - oci->buffer + needed) > oci->size)) {
335             /* no data, or the request is too big to fit in the buffer */
336
337             if ((gotnow > 0) && (oci->bufptr != oci->buffer))
338                 /* save the data we've already read */
339                 memmove(oci->buffer, oci->bufptr, gotnow);
340             if (needed > oci->size) {
341                 /* make buffer bigger to accomodate request */
342                 char *ibuf;
343
344                 ibuf = (char *) realloc(oci->buffer, needed);
345                 if (!ibuf) {
346                     YieldControlDeath();
347                     return -1;
348                 }
349                 oci->size = needed;
350                 oci->buffer = ibuf;
351             }
352             oci->bufptr = oci->buffer;
353             oci->bufcnt = gotnow;
354         }
355         /*  XXX this is a workaround.  This function is sometimes called
356          *  after the trans_conn has been freed.  In this case trans_conn
357          *  will be null.  Really ought to restructure things so that we
358          *  never get here in those circumstances.
359          */
360         if (!oc->trans_conn) {
361             /*  treat as if an error occured on the read, which is what
362              *  used to happen
363              */
364             YieldControlDeath();
365             return -1;
366         }
367         result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt,
368                                  oci->size - oci->bufcnt);
369         if (result <= 0) {
370             if ((result < 0) && ETEST(errno)) {
371 #if defined(SVR4) && defined(__i386__) && !defined(sun)
372                 if (0)
373 #endif
374                 {
375                     YieldControlNoInput(fd);
376                     return 0;
377                 }
378             }
379             YieldControlDeath();
380             return -1;
381         }
382         oci->bufcnt += result;
383         gotnow += result;
384         /* free up some space after huge requests */
385         if ((oci->size > BUFWATERMARK) &&
386             (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) {
387             char *ibuf;
388
389             ibuf = (char *) realloc(oci->buffer, BUFSIZE);
390             if (ibuf) {
391                 oci->size = BUFSIZE;
392                 oci->buffer = ibuf;
393                 oci->bufptr = ibuf + oci->bufcnt - gotnow;
394             }
395         }
396         if (need_header && gotnow >= needed) {
397             /* We wanted an xReq, now we've gotten it. */
398             request = (xReq *) oci->bufptr;
399             needed = get_req_len(request, client);
400             if (!needed && client->big_requests) {
401                 move_header = TRUE;
402                 if (gotnow < sizeof(xBigReq))
403                     needed = bytes_to_int32(sizeof(xBigReq));
404                 else
405                     needed = get_big_req_len(request, client);
406             }
407             client->req_len = needed;
408             needed <<= 2;
409         }
410         if (gotnow < needed) {
411             /* Still don't have enough; punt. */
412             YieldControlNoInput(fd);
413             return 0;
414         }
415     }
416     if (needed == 0) {
417         if (client->big_requests)
418             needed = sizeof(xBigReq);
419         else
420             needed = sizeof(xReq);
421     }
422
423     /* If there are bytes to ignore, ignore them now. */
424
425     if (oci->ignoreBytes > 0) {
426         assert(needed == oci->ignoreBytes || needed == oci->size);
427         /*
428          * The _XSERVTransRead call above may return more or fewer bytes than we
429          * want to ignore.  Ignore the smaller of the two sizes.
430          */
431         if (gotnow < needed) {
432             oci->ignoreBytes -= gotnow;
433             oci->bufptr += gotnow;
434             gotnow = 0;
435         }
436         else {
437             oci->ignoreBytes -= needed;
438             oci->bufptr += needed;
439             gotnow -= needed;
440         }
441         needed = 0;
442     }
443
444     oci->lenLastReq = needed;
445
446     /*
447      *  Check to see if client has at least one whole request in the
448      *  buffer beyond the request we're returning to the caller.
449      *  If there is only a partial request, treat like buffer
450      *  is empty so that select() will be called again and other clients
451      *  can get into the queue.   
452      */
453
454     gotnow -= needed;
455     if (gotnow >= sizeof(xReq)) {
456         request = (xReq *) (oci->bufptr + needed);
457         if (gotnow >= (result = (get_req_len(request, client) << 2))
458             && (result ||
459                 (client->big_requests &&
460                  (gotnow >= sizeof(xBigReq) &&
461                   gotnow >= (get_big_req_len(request, client) << 2))))
462             )
463             FD_SET(fd, &ClientsWithInput);
464         else {
465             if (!SmartScheduleDisable)
466                 FD_CLR(fd, &ClientsWithInput);
467             else
468                 YieldControlNoInput(fd);
469         }
470     }
471     else {
472         if (!gotnow)
473             AvailableInput = oc;
474         if (!SmartScheduleDisable)
475             FD_CLR(fd, &ClientsWithInput);
476         else
477             YieldControlNoInput(fd);
478     }
479     if (SmartScheduleDisable)
480         if (++timesThisConnection >= MAX_TIMES_PER)
481             YieldControl();
482     if (move_header) {
483         request = (xReq *) oci->bufptr;
484         oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
485         *(xReq *) oci->bufptr = *request;
486         oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq));
487         client->req_len -= bytes_to_int32(sizeof(xBigReq) - sizeof(xReq));
488     }
489     client->requestBuffer = (void *) oci->bufptr;
490 #ifdef DEBUG_COMMUNICATION
491     {
492         xReq *req = client->requestBuffer;
493
494         ErrorF("REQUEST: ClientIDX: %i, type: 0x%x data: 0x%x len: %i\n",
495                client->index, req->reqType, req->data, req->length);
496     }
497 #endif
498     return needed;
499 }
500
501 #if XTRANS_SEND_FDS
502 int
503 ReadFdFromClient(ClientPtr client)
504 {
505     int fd = -1;
506
507     if (client->req_fds > 0) {
508         OsCommPtr oc = (OsCommPtr) client->osPrivate;
509
510         --client->req_fds;
511         fd = _XSERVTransRecvFd(oc->trans_conn);
512     } else
513         LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n");
514     return fd;
515 }
516
517 int
518 WriteFdToClient(ClientPtr client, int fd, Bool do_close)
519 {
520     OsCommPtr oc = (OsCommPtr) client->osPrivate;
521
522     return _XSERVTransSendFd(oc->trans_conn, fd, do_close);
523 }
524 #endif
525
526 /*****************************************************************
527  * InsertFakeRequest
528  *    Splice a consed up (possibly partial) request in as the next request.
529  *
530  **********************/
531
532 Bool
533 InsertFakeRequest(ClientPtr client, char *data, int count)
534 {
535     OsCommPtr oc = (OsCommPtr) client->osPrivate;
536     ConnectionInputPtr oci = oc->input;
537     int fd = oc->fd;
538     int gotnow, moveup;
539
540     NextAvailableInput(oc);
541
542     if (!oci) {
543         if ((oci = FreeInputs))
544             FreeInputs = oci->next;
545         else if (!(oci = AllocateInputBuffer()))
546             return FALSE;
547         oc->input = oci;
548     }
549     oci->bufptr += oci->lenLastReq;
550     oci->lenLastReq = 0;
551     gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
552     if ((gotnow + count) > oci->size) {
553         char *ibuf;
554
555         ibuf = (char *) realloc(oci->buffer, gotnow + count);
556         if (!ibuf)
557             return FALSE;
558         oci->size = gotnow + count;
559         oci->buffer = ibuf;
560         oci->bufptr = ibuf + oci->bufcnt - gotnow;
561     }
562     moveup = count - (oci->bufptr - oci->buffer);
563     if (moveup > 0) {
564         if (gotnow > 0)
565             memmove(oci->bufptr + moveup, oci->bufptr, gotnow);
566         oci->bufptr += moveup;
567         oci->bufcnt += moveup;
568     }
569     memmove(oci->bufptr - count, data, count);
570     oci->bufptr -= count;
571     gotnow += count;
572     if ((gotnow >= sizeof(xReq)) &&
573         (gotnow >= (int) (get_req_len((xReq *) oci->bufptr, client) << 2)))
574         FD_SET(fd, &ClientsWithInput);
575     else
576         YieldControlNoInput(fd);
577     return TRUE;
578 }
579
580 /*****************************************************************
581  * ResetRequestFromClient
582  *    Reset to reexecute the current request, and yield.
583  *
584  **********************/
585
586 void
587 ResetCurrentRequest(ClientPtr client)
588 {
589     OsCommPtr oc = (OsCommPtr) client->osPrivate;
590     register ConnectionInputPtr oci = oc->input;
591     int fd = oc->fd;
592     register xReq *request;
593     int gotnow, needed;
594
595     if (AvailableInput == oc)
596         AvailableInput = (OsCommPtr) NULL;
597     oci->lenLastReq = 0;
598     gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
599     if (gotnow < sizeof(xReq)) {
600         YieldControlNoInput(fd);
601     }
602     else {
603         request = (xReq *) oci->bufptr;
604         needed = get_req_len(request, client);
605         if (!needed && client->big_requests) {
606             oci->bufptr -= sizeof(xBigReq) - sizeof(xReq);
607             *(xReq *) oci->bufptr = *request;
608             ((xBigReq *) oci->bufptr)->length = client->req_len;
609             if (client->swapped) {
610                 swapl(&((xBigReq *) oci->bufptr)->length);
611             }
612         }
613         if (gotnow >= (needed << 2)) {
614             if (FD_ISSET(fd, &AllClients)) {
615                 FD_SET(fd, &ClientsWithInput);
616             }
617             else {
618                 FD_SET(fd, &IgnoredClientsWithInput);
619             }
620             YieldControl();
621         }
622         else
623             YieldControlNoInput(fd);
624     }
625 }
626
627  /********************
628  * FlushAllOutput()
629  *    Flush all clients with output.  However, if some client still
630  *    has input in the queue (more requests), then don't flush.  This
631  *    will prevent the output queue from being flushed every time around
632  *    the round robin queue.  Now, some say that it SHOULD be flushed
633  *    every time around, but...
634  *
635  **********************/
636
637 void
638 FlushAllOutput(void)
639 {
640     register int index, base;
641     register fd_mask mask;      /* raphael */
642     OsCommPtr oc;
643     register ClientPtr client;
644     Bool newoutput = NewOutputPending;
645
646 #if defined(WIN32)
647     fd_set newOutputPending;
648 #endif
649
650     if (FlushCallback)
651         CallCallbacks(&FlushCallback, NULL);
652
653     if (!newoutput)
654         return;
655
656     /*
657      * It may be that some client still has critical output pending,
658      * but he is not yet ready to receive it anyway, so we will
659      * simply wait for the select to tell us when he's ready to receive.
660      */
661     CriticalOutputPending = FALSE;
662     NewOutputPending = FALSE;
663
664 #ifndef WIN32
665     for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) {
666         mask = OutputPending.fds_bits[base];
667         OutputPending.fds_bits[base] = 0;
668         while (mask) {
669             index = ffs(mask) - 1;
670             mask &= ~lowbit(mask);
671             if ((index =
672                  ConnectionTranslation[(base * (sizeof(fd_mask) * 8)) +
673                                        index]) == 0)
674                 continue;
675             client = clients[index];
676             if (client->clientGone)
677                 continue;
678             oc = (OsCommPtr) client->osPrivate;
679             if (FD_ISSET(oc->fd, &ClientsWithInput)) {
680                 FD_SET(oc->fd, &OutputPending); /* set the bit again */
681                 NewOutputPending = TRUE;
682             }
683             else
684                 (void) FlushClient(client, oc, (char *) NULL, 0);
685         }
686     }
687 #else                           /* WIN32 */
688     FD_ZERO(&newOutputPending);
689     for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) {
690         index = XFD_FD(&OutputPending, base);
691         if ((index = GetConnectionTranslation(index)) == 0)
692             continue;
693         client = clients[index];
694         if (client->clientGone)
695             continue;
696         oc = (OsCommPtr) client->osPrivate;
697         if (FD_ISSET(oc->fd, &ClientsWithInput)) {
698             FD_SET(oc->fd, &newOutputPending);  /* set the bit again */
699             NewOutputPending = TRUE;
700         }
701         else
702             (void) FlushClient(client, oc, (char *) NULL, 0);
703     }
704     XFD_COPYSET(&newOutputPending, &OutputPending);
705 #endif                          /* WIN32 */
706 }
707
708 void
709 FlushIfCriticalOutputPending(void)
710 {
711     if (CriticalOutputPending)
712         FlushAllOutput();
713 }
714
715 void
716 SetCriticalOutputPending(void)
717 {
718     CriticalOutputPending = TRUE;
719 }
720
721 /*****************
722  * WriteToClient
723  *    Copies buf into ClientPtr.buf if it fits (with padding), else
724  *    flushes ClientPtr.buf and buf to client.  As of this writing,
725  *    every use of WriteToClient is cast to void, and the result
726  *    is ignored.  Potentially, this could be used by requests
727  *    that are sending several chunks of data and want to break
728  *    out of a loop on error.  Thus, we will leave the type of
729  *    this routine as int.
730  *****************/
731
732 int
733 WriteToClient(ClientPtr who, int count, const void *__buf)
734 {
735     OsCommPtr oc;
736     ConnectionOutputPtr oco;
737     int padBytes;
738     const char *buf = __buf;
739
740 #ifdef DEBUG_COMMUNICATION
741     Bool multicount = FALSE;
742 #endif
743     if (!count || !who || who == serverClient || who->clientGone)
744         return 0;
745     oc = who->osPrivate;
746     oco = oc->output;
747 #ifdef DEBUG_COMMUNICATION
748     {
749         char info[128];
750         xError *err;
751         xGenericReply *rep;
752         xEvent *ev;
753
754         if (!who->replyBytesRemaining) {
755             switch (buf[0]) {
756             case X_Reply:
757                 rep = (xGenericReply *) buf;
758                 if (rep->sequenceNumber == who->sequence) {
759                     snprintf(info, 127, "Xreply: type: 0x%x data: 0x%x "
760                              "len: %i seq#: 0x%x", rep->type, rep->data1,
761                              rep->length, rep->sequenceNumber);
762                     multicount = TRUE;
763                 }
764                 break;
765             case X_Error:
766                 err = (xError *) buf;
767                 snprintf(info, 127, "Xerror: Code: 0x%x resID: 0x%x maj: 0x%x "
768                          "min: %x", err->errorCode, err->resourceID,
769                          err->minorCode, err->majorCode);
770                 break;
771             default:
772                 if ((buf[0] & 0x7f) == KeymapNotify)
773                     snprintf(info, 127, "KeymapNotifyEvent: %i", buf[0]);
774                 else {
775                     ev = (xEvent *) buf;
776                     snprintf(info, 127, "XEvent: type: 0x%x detail: 0x%x "
777                              "seq#: 0x%x", ev->u.u.type, ev->u.u.detail,
778                              ev->u.u.sequenceNumber);
779                 }
780             }
781             ErrorF("REPLY: ClientIDX: %i %s\n", who->index, info);
782         }
783         else
784             multicount = TRUE;
785     }
786 #endif
787
788     if (!oco) {
789         if ((oco = FreeOutputs)) {
790             FreeOutputs = oco->next;
791         }
792         else if (!(oco = AllocateOutputBuffer())) {
793             if (oc->trans_conn) {
794                 _XSERVTransDisconnect(oc->trans_conn);
795                 _XSERVTransClose(oc->trans_conn);
796                 oc->trans_conn = NULL;
797             }
798             MarkClientException(who);
799             return -1;
800         }
801         oc->output = oco;
802     }
803
804     padBytes = padding_for_int32(count);
805
806     if (ReplyCallback) {
807         ReplyInfoRec replyinfo;
808
809         replyinfo.client = who;
810         replyinfo.replyData = buf;
811         replyinfo.dataLenBytes = count + padBytes;
812         replyinfo.padBytes = padBytes;
813         if (who->replyBytesRemaining) { /* still sending data of an earlier reply */
814             who->replyBytesRemaining -= count + padBytes;
815             replyinfo.startOfReply = FALSE;
816             replyinfo.bytesRemaining = who->replyBytesRemaining;
817             CallCallbacks((&ReplyCallback), (void *) &replyinfo);
818         }
819         else if (who->clientState == ClientStateRunning && buf[0] == X_Reply) { /* start of new reply */
820             CARD32 replylen;
821             unsigned long bytesleft;
822
823             replylen = ((const xGenericReply *) buf)->length;
824             if (who->swapped)
825                 swapl(&replylen);
826             bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes;
827             replyinfo.startOfReply = TRUE;
828             replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft;
829             CallCallbacks((&ReplyCallback), (void *) &replyinfo);
830         }
831     }
832 #ifdef DEBUG_COMMUNICATION
833     else if (multicount) {
834         if (who->replyBytesRemaining) {
835             who->replyBytesRemaining -= (count + padBytes);
836         }
837         else {
838             CARD32 replylen;
839
840             replylen = ((xGenericReply *) buf)->length;
841             who->replyBytesRemaining =
842                 (replylen * 4) + SIZEOF(xReply) - count - padBytes;
843         }
844     }
845 #endif
846     if (oco->count == 0 || oco->count + count + padBytes > oco->size) {
847         FD_CLR(oc->fd, &OutputPending);
848         if (!XFD_ANYSET(&OutputPending)) {
849             CriticalOutputPending = FALSE;
850             NewOutputPending = FALSE;
851         }
852
853         if (FlushCallback)
854             CallCallbacks(&FlushCallback, NULL);
855
856         return FlushClient(who, oc, buf, count);
857     }
858
859     NewOutputPending = TRUE;
860     FD_SET(oc->fd, &OutputPending);
861     memmove((char *) oco->buf + oco->count, buf, count);
862     oco->count += count;
863     if (padBytes) {
864         memset(oco->buf + oco->count, '\0', padBytes);
865         oco->count += padBytes;
866     }
867     return count;
868 }
869
870  /********************
871  * FlushClient()
872  *    If the client isn't keeping up with us, then we try to continue
873  *    buffering the data and set the apropriate bit in ClientsWritable
874  *    (which is used by WaitFor in the select).  If the connection yields
875  *    a permanent error, or we can't allocate any more space, we then
876  *    close the connection.
877  *
878  **********************/
879
880 int
881 FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
882 {
883     ConnectionOutputPtr oco = oc->output;
884     int connection = oc->fd;
885     XtransConnInfo trans_conn = oc->trans_conn;
886     struct iovec iov[3];
887     static char padBuffer[3];
888     const char *extraBuf = __extraBuf;
889     long written;
890     long padsize;
891     long notWritten;
892     long todo;
893
894     if (!oco)
895         return 0;
896     written = 0;
897     padsize = padding_for_int32(extraCount);
898     notWritten = oco->count + extraCount + padsize;
899     if (!notWritten)
900         return 0;
901
902     todo = notWritten;
903     while (notWritten) {
904         long before = written;  /* amount of whole thing written */
905         long remain = todo;     /* amount to try this time, <= notWritten */
906         int i = 0;
907         long len;
908
909         /* You could be very general here and have "in" and "out" iovecs
910          * and write a loop without using a macro, but what the heck.  This
911          * translates to:
912          *
913          *     how much of this piece is new?
914          *     if more new then we are trying this time, clamp
915          *     if nothing new
916          *         then bump down amount already written, for next piece
917          *         else put new stuff in iovec, will need all of next piece
918          *
919          * Note that todo had better be at least 1 or else we'll end up
920          * writing 0 iovecs.
921          */
922 #define InsertIOV(pointer, length) \
923         len = (length) - before; \
924         if (len > remain) \
925             len = remain; \
926         if (len <= 0) { \
927             before = (-len); \
928         } else { \
929             iov[i].iov_len = len; \
930             iov[i].iov_base = (pointer) + before;       \
931             i++; \
932             remain -= len; \
933             before = 0; \
934         }
935
936         InsertIOV((char *) oco->buf, oco->count)
937             InsertIOV((char *) extraBuf, extraCount)
938             InsertIOV(padBuffer, padsize)
939
940             errno = 0;
941         if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0) {
942             written += len;
943             notWritten -= len;
944             todo = notWritten;
945         }
946         else if (ETEST(errno)
947 #ifdef SUNSYSV                  /* check for another brain-damaged OS bug */
948                  || (errno == 0)
949 #endif
950 #ifdef EMSGSIZE                 /* check for another brain-damaged OS bug */
951                  || ((errno == EMSGSIZE) && (todo == 1))
952 #endif
953             ) {
954             /* If we've arrived here, then the client is stuffed to the gills
955                and not ready to accept more.  Make a note of it and buffer
956                the rest. */
957             FD_SET(connection, &ClientsWriteBlocked);
958             AnyClientsWriteBlocked = TRUE;
959
960             if (written < oco->count) {
961                 if (written > 0) {
962                     oco->count -= written;
963                     memmove((char *) oco->buf,
964                             (char *) oco->buf + written, oco->count);
965                     written = 0;
966                 }
967             }
968             else {
969                 written -= oco->count;
970                 oco->count = 0;
971             }
972
973             if (notWritten > oco->size) {
974                 unsigned char *obuf;
975
976                 obuf = (unsigned char *) realloc(oco->buf,
977                                                  notWritten + BUFSIZE);
978                 if (!obuf) {
979                     _XSERVTransDisconnect(oc->trans_conn);
980                     _XSERVTransClose(oc->trans_conn);
981                     oc->trans_conn = NULL;
982                     MarkClientException(who);
983                     oco->count = 0;
984                     return -1;
985                 }
986                 oco->size = notWritten + BUFSIZE;
987                 oco->buf = obuf;
988             }
989
990             /* If the amount written extended into the padBuffer, then the
991                difference "extraCount - written" may be less than 0 */
992             if ((len = extraCount - written) > 0)
993                 memmove((char *) oco->buf + oco->count,
994                         extraBuf + written, len);
995
996             oco->count = notWritten;    /* this will include the pad */
997             /* return only the amount explicitly requested */
998             return extraCount;
999         }
1000 #ifdef EMSGSIZE                 /* check for another brain-damaged OS bug */
1001         else if (errno == EMSGSIZE) {
1002             todo >>= 1;
1003         }
1004 #endif
1005         else {
1006             if (oc->trans_conn) {
1007                 _XSERVTransDisconnect(oc->trans_conn);
1008                 _XSERVTransClose(oc->trans_conn);
1009                 oc->trans_conn = NULL;
1010             }
1011             MarkClientException(who);
1012             oco->count = 0;
1013             return -1;
1014         }
1015     }
1016
1017     /* everything was flushed out */
1018     oco->count = 0;
1019     /* check to see if this client was write blocked */
1020     if (AnyClientsWriteBlocked) {
1021         FD_CLR(oc->fd, &ClientsWriteBlocked);
1022         if (!XFD_ANYSET(&ClientsWriteBlocked))
1023             AnyClientsWriteBlocked = FALSE;
1024     }
1025     if (oco->size > BUFWATERMARK) {
1026         free(oco->buf);
1027         free(oco);
1028     }
1029     else {
1030         oco->next = FreeOutputs;
1031         FreeOutputs = oco;
1032     }
1033     oc->output = (ConnectionOutputPtr) NULL;
1034     return extraCount;          /* return only the amount explicitly requested */
1035 }
1036
1037 static ConnectionInputPtr
1038 AllocateInputBuffer(void)
1039 {
1040     ConnectionInputPtr oci;
1041
1042     oci = malloc(sizeof(ConnectionInput));
1043     if (!oci)
1044         return NULL;
1045     oci->buffer = malloc(BUFSIZE);
1046     if (!oci->buffer) {
1047         free(oci);
1048         return NULL;
1049     }
1050     oci->size = BUFSIZE;
1051     oci->bufptr = oci->buffer;
1052     oci->bufcnt = 0;
1053     oci->lenLastReq = 0;
1054     oci->ignoreBytes = 0;
1055     return oci;
1056 }
1057
1058 static ConnectionOutputPtr
1059 AllocateOutputBuffer(void)
1060 {
1061     ConnectionOutputPtr oco;
1062
1063     oco = malloc(sizeof(ConnectionOutput));
1064     if (!oco)
1065         return NULL;
1066     oco->buf = calloc(1, BUFSIZE);
1067     if (!oco->buf) {
1068         free(oco);
1069         return NULL;
1070     }
1071     oco->size = BUFSIZE;
1072     oco->count = 0;
1073     return oco;
1074 }
1075
1076 void
1077 FreeOsBuffers(OsCommPtr oc)
1078 {
1079     ConnectionInputPtr oci;
1080     ConnectionOutputPtr oco;
1081
1082     if (AvailableInput == oc)
1083         AvailableInput = (OsCommPtr) NULL;
1084     if ((oci = oc->input)) {
1085         if (FreeInputs) {
1086             free(oci->buffer);
1087             free(oci);
1088         }
1089         else {
1090             FreeInputs = oci;
1091             oci->next = (ConnectionInputPtr) NULL;
1092             oci->bufptr = oci->buffer;
1093             oci->bufcnt = 0;
1094             oci->lenLastReq = 0;
1095             oci->ignoreBytes = 0;
1096         }
1097     }
1098     if ((oco = oc->output)) {
1099         if (FreeOutputs) {
1100             free(oco->buf);
1101             free(oco);
1102         }
1103         else {
1104             FreeOutputs = oco;
1105             oco->next = (ConnectionOutputPtr) NULL;
1106             oco->count = 0;
1107         }
1108     }
1109 }
1110
1111 void
1112 ResetOsBuffers(void)
1113 {
1114     ConnectionInputPtr oci;
1115     ConnectionOutputPtr oco;
1116
1117     while ((oci = FreeInputs)) {
1118         FreeInputs = oci->next;
1119         free(oci->buffer);
1120         free(oci);
1121     }
1122     while ((oco = FreeOutputs)) {
1123         FreeOutputs = oco->next;
1124         free(oco->buf);
1125         free(oco);
1126     }
1127 }