summaryrefslogtreecommitdiff
path: root/os/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/io.c')
-rw-r--r--os/io.c1339
1 files changed, 0 insertions, 1339 deletions
diff --git a/os/io.c b/os/io.c
deleted file mode 100644
index cf8a0343e..000000000
--- a/os/io.c
+++ /dev/null
@@ -1,1339 +0,0 @@
-/***********************************************************
-
-Copyright 1987, 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
-******************************************************************/
-/* $Xorg: io.c,v 1.6 2001/02/09 02:05:23 xorgcvs Exp $ */
-/*****************************************************************
- * i/o functions
- *
- * WriteToClient, ReadRequestFromClient
- * InsertFakeRequest, ResetCurrentRequest
- *
- *****************************************************************/
-/* $XFree86: xc/programs/Xserver/os/io.c,v 3.35 2003/04/27 21:31:08 herrb Exp $ */
-
-#if 0
-#define DEBUG_COMMUNICATION
-#endif
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-#include <stdio.h>
-#include <X11/Xtrans.h>
-#include "Xmd.h"
-#include <errno.h>
-#if !defined(__UNIXOS2__) && !defined(WIN32)
-#ifndef Lynx
-#include <sys/uio.h>
-#else
-#include <uio.h>
-#endif
-#endif
-#include "X.h"
-#define NEED_REPLIES
-#include "Xproto.h"
-#include "os.h"
-#include "osdep.h"
-#include "Xpoll.h"
-#include "opaque.h"
-#include "dixstruct.h"
-#include "misc.h"
-#ifdef LBX
-#include "colormapst.h"
-#include "propertyst.h"
-#include "lbxserve.h"
-#endif
-
-CallbackListPtr ReplyCallback;
-CallbackListPtr FlushCallback;
-
-/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
- * systems are broken and return EWOULDBLOCK when they should return EAGAIN
- */
-#ifndef __UNIXOS2__
-#if defined(EAGAIN) && defined(EWOULDBLOCK)
-#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
-#else
-#ifdef EAGAIN
-#define ETEST(err) (err == EAGAIN)
-#else
-#define ETEST(err) (err == EWOULDBLOCK)
-#endif
-#endif
-#else /* __UNIXOS2__ Writing to full pipes may return ENOSPC */
-#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK || err == ENOSPC)
-#endif
-
-Bool CriticalOutputPending;
-int timesThisConnection = 0;
-ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL;
-ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL;
-OsCommPtr AvailableInput = (OsCommPtr)NULL;
-
-#define get_req_len(req,cli) ((cli)->swapped ? \
- lswaps((req)->length) : (req)->length)
-
-#ifdef BIGREQS
-#include "bigreqstr.h"
-
-#define get_big_req_len(req,cli) ((cli)->swapped ? \
- lswapl(((xBigReq *)(req))->length) : \
- ((xBigReq *)(req))->length)
-#endif
-
-#define MAX_TIMES_PER 10
-
-/*
- * A lot of the code in this file manipulates a ConnectionInputPtr:
- *
- * -----------------------------------------------
- * |------- bufcnt ------->| | |
- * | |- gotnow ->| | |
- * | |-------- needed ------>| |
- * |-----------+--------- size --------+---------->|
- * -----------------------------------------------
- * ^ ^
- * | |
- * buffer bufptr
- *
- * buffer is a pointer to the start of the buffer.
- * bufptr points to the start of the current request.
- * bufcnt counts how many bytes are in the buffer.
- * size is the size of the buffer in bytes.
- *
- * In several of the functions, gotnow and needed are local variables
- * that do the following:
- *
- * gotnow is the number of bytes of the request that we're
- * trying to read that are currently in the buffer.
- * Typically, gotnow = (buffer + bufcnt) - bufptr
- *
- * needed = the length of the request that we're trying to
- * read. Watch out: needed sometimes counts bytes and sometimes
- * counts CARD32's.
- */
-
-
-/*****************************************************************
- * ReadRequestFromClient
- * Returns one request in client->requestBuffer. The request
- * length will be in client->req_len. Return status is:
- *
- * > 0 if successful, specifies length in bytes of the request
- * = 0 if entire request is not yet available
- * < 0 if client should be terminated
- *
- * The request returned must be contiguous so that it can be
- * cast in the dispatcher to the correct request type. Because requests
- * are variable length, ReadRequestFromClient() must look at the first 4
- * or 8 bytes of a request to determine the length (the request length is
- * in the 3rd and 4th bytes of the request unless it is a Big Request
- * (see the Big Request Extension), in which case the 3rd and 4th bytes
- * are zero and the following 4 bytes are the request length.
- *
- * Note: in order to make the server scheduler (WaitForSomething())
- * "fair", the ClientsWithInput mask is used. This mask tells which
- * clients have FULL requests left in their buffers. Clients with
- * partial requests require a read. Basically, client buffers
- * are drained before select() is called again. But, we can't keep
- * reading from a client that is sending buckets of data (or has
- * a partial request) because others clients need to be scheduled.
- *****************************************************************/
-
-#define YieldControl() \
- { isItTimeToYield = TRUE; \
- timesThisConnection = 0; }
-#define YieldControlNoInput() \
- { YieldControl(); \
- FD_CLR(fd, &ClientsWithInput); }
-#define YieldControlDeath() \
- { timesThisConnection = 0; }
-
-#ifdef hpux_not_tog
-#define LBX_NEED_OLD_SYMBOL_FOR_LOADABLES
-#endif
-
-#ifdef LBX
-#ifdef LBX_NEED_OLD_SYMBOL_FOR_LOADABLES
-#undef ReadRequestFromClient
-int
-ReadRequestFromClient(ClientPtr client)
-{
- return (*client->readRequest)(client);
-}
-#endif
-int
-StandardReadRequestFromClient(ClientPtr client)
-#else
-int
-ReadRequestFromClient(ClientPtr client)
-#endif
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- ConnectionInputPtr oci = oc->input;
- int fd = oc->fd;
- unsigned int gotnow, needed;
- int result;
- register xReq *request;
- Bool need_header;
-#ifdef BIGREQS
- Bool move_header;
-#endif
-
- /* If an input buffer was empty, either free it if it is too big
- * or link it into our list of free input buffers. This means that
- * different clients can share the same input buffer (at different
- * times). This was done to save memory.
- */
-
- if (AvailableInput)
- {
- if (AvailableInput != oc)
- {
- register ConnectionInputPtr aci = AvailableInput->input;
- if (aci->size > BUFWATERMARK)
- {
- xfree(aci->buffer);
- xfree(aci);
- }
- else
- {
- aci->next = FreeInputs;
- FreeInputs = aci;
- }
- AvailableInput->input = (ConnectionInputPtr)NULL;
- }
- AvailableInput = (OsCommPtr)NULL;
- }
-
- /* make sure we have an input buffer */
-
- if (!oci)
- {
- if ((oci = FreeInputs))
- {
- FreeInputs = oci->next;
- }
- else if (!(oci = AllocateInputBuffer()))
- {
- YieldControlDeath();
- return -1;
- }
- oc->input = oci;
- }
-
- /* advance to start of next request */
-
- oci->bufptr += oci->lenLastReq;
-
- need_header = FALSE;
-#ifdef BIGREQS
- move_header = FALSE;
-#endif
- gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
- if (gotnow < sizeof(xReq))
- {
- /* We don't have an entire xReq yet. Can't tell how big
- * the request will be until we get the whole xReq.
- */
- needed = sizeof(xReq);
- need_header = TRUE;
- }
- else
- {
- /* We have a whole xReq. We can tell how big the whole
- * request will be unless it is a Big Request.
- */
- request = (xReq *)oci->bufptr;
- needed = get_req_len(request, client);
-#ifdef BIGREQS
- if (!needed && client->big_requests)
- {
- /* It's a Big Request. */
- move_header = TRUE;
- if (gotnow < sizeof(xBigReq))
- {
- /* Still need more data to tell just how big. */
- needed = sizeof(xBigReq) >> 2; /* needed is in CARD32s now */
- need_header = TRUE;
- }
- else
- needed = get_big_req_len(request, client);
- }
-#endif
- client->req_len = needed;
- needed <<= 2; /* needed is in bytes now */
- }
- if (gotnow < needed)
- {
- /* Need to read more data, either so that we can get a
- * complete xReq (if need_header is TRUE), a complete
- * xBigReq (if move_header is TRUE), or the rest of the
- * request (if need_header and move_header are both FALSE).
- */
-
- oci->lenLastReq = 0;
- if (needed > MAXBUFSIZE)
- {
- /* request is too big for us to handle */
- YieldControlDeath();
- return -1;
- }
- if ((gotnow == 0) ||
- ((oci->bufptr - oci->buffer + needed) > oci->size))
- {
- /* no data, or the request is too big to fit in the buffer */
-
- if ((gotnow > 0) && (oci->bufptr != oci->buffer))
- /* save the data we've already read */
- memmove(oci->buffer, oci->bufptr, gotnow);
- if (needed > oci->size)
- {
- /* make buffer bigger to accomodate request */
- char *ibuf;
-
- ibuf = (char *)xrealloc(oci->buffer, needed);
- if (!ibuf)
- {
- YieldControlDeath();
- return -1;
- }
- oci->size = needed;
- oci->buffer = ibuf;
- }
- oci->bufptr = oci->buffer;
- oci->bufcnt = gotnow;
- }
- /* XXX this is a workaround. This function is sometimes called
- * after the trans_conn has been freed. In this case trans_conn
- * will be null. Really ought to restructure things so that we
- * never get here in those circumstances.
- */
- if (!oc->trans_conn)
- {
- /* treat as if an error occured on the read, which is what
- * used to happen
- */
- YieldControlDeath();
- return -1;
- }
-#ifdef LBX
- if (oc->proxy && oc->proxy->compHandle)
- result = (*oc->proxy->streamOpts.streamCompRead)(fd,
- (unsigned char *)oci->buffer + oci->bufcnt,
- oci->size - oci->bufcnt);
- else
-#endif
- result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt,
- oci->size - oci->bufcnt);
- if (result <= 0)
- {
- if ((result < 0) && ETEST(errno))
- {
-#if defined(SVR4) && defined(i386) && !defined(sun)
-#if defined(LBX) && 0
- /*
- * For LBX connections, we can get a valid EWOULDBLOCK
- * There is probably a better way of distinguishing LBX
- * connections, but this works. (DHD)
- */
- extern int LbxRead();
- if (oc->Read == LbxRead)
-#else
- if (0)
-#endif
-#endif
- {
- YieldControlNoInput();
- return 0;
- }
- }
- YieldControlDeath();
- return -1;
- }
- oci->bufcnt += result;
- gotnow += result;
- /* free up some space after huge requests */
- if ((oci->size > BUFWATERMARK) &&
- (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE))
- {
- char *ibuf;
-
- ibuf = (char *)xrealloc(oci->buffer, BUFSIZE);
- if (ibuf)
- {
- oci->size = BUFSIZE;
- oci->buffer = ibuf;
- oci->bufptr = ibuf + oci->bufcnt - gotnow;
- }
- }
- if (need_header && gotnow >= needed)
- {
- /* We wanted an xReq, now we've gotten it. */
- request = (xReq *)oci->bufptr;
- needed = get_req_len(request, client);
-#ifdef BIGREQS
- if (!needed && client->big_requests)
- {
- move_header = TRUE;
- if (gotnow < sizeof(xBigReq))
- needed = sizeof(xBigReq) >> 2;
- else
- needed = get_big_req_len(request, client);
- }
-#endif
- client->req_len = needed;
- needed <<= 2;
- }
- if (gotnow < needed)
- {
- /* Still don't have enough; punt. */
- YieldControlNoInput();
- return 0;
- }
- }
- if (needed == 0)
- {
-#ifdef BIGREQS
- if (client->big_requests)
- needed = sizeof(xBigReq);
- else
-#endif
- needed = sizeof(xReq);
- }
- oci->lenLastReq = needed;
-
- /*
- * Check to see if client has at least one whole request in the
- * buffer beyond the request we're returning to the caller.
- * If there is only a partial request, treat like buffer
- * is empty so that select() will be called again and other clients
- * can get into the queue.
- */
-
- gotnow -= needed;
- if (gotnow >= sizeof(xReq))
- {
- request = (xReq *)(oci->bufptr + needed);
- if (gotnow >= (result = (get_req_len(request, client) << 2))
-#ifdef BIGREQS
- && (result ||
- (client->big_requests &&
- (gotnow >= sizeof(xBigReq) &&
- gotnow >= (get_big_req_len(request, client) << 2))))
-#endif
- )
- FD_SET(fd, &ClientsWithInput);
- else
- {
-#ifdef SMART_SCHEDULE
- if (!SmartScheduleDisable)
- FD_CLR(fd, &ClientsWithInput);
- else
-#endif
- YieldControlNoInput();
- }
- }
- else
- {
- if (!gotnow)
- AvailableInput = oc;
-#ifdef SMART_SCHEDULE
- if (!SmartScheduleDisable)
- FD_CLR(fd, &ClientsWithInput);
- else
-#endif
- YieldControlNoInput();
- }
-#ifdef SMART_SCHEDULE
- if (SmartScheduleDisable)
-#endif
- if (++timesThisConnection >= MAX_TIMES_PER)
- YieldControl();
-#ifdef BIGREQS
- if (move_header)
- {
- request = (xReq *)oci->bufptr;
- oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
- *(xReq *)oci->bufptr = *request;
- oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq));
- client->req_len -= (sizeof(xBigReq) - sizeof(xReq)) >> 2;
- }
-#endif
- client->requestBuffer = (pointer)oci->bufptr;
-#ifdef DEBUG_COMMUNICATION
- {
- xReq *req = client->requestBuffer;
- ErrorF("REQUEST: ClientIDX: %i, type: 0x%x data: 0x%x len: %i\n",
- client->index,req->reqType,req->data,req->length);
- }
-#endif
- return needed;
-}
-
-/*****************************************************************
- * InsertFakeRequest
- * Splice a consed up (possibly partial) request in as the next request.
- *
- **********************/
-
-Bool
-InsertFakeRequest(ClientPtr client, char *data, int count)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- ConnectionInputPtr oci = oc->input;
- int fd = oc->fd;
- int gotnow, moveup;
-
- if (AvailableInput)
- {
- if (AvailableInput != oc)
- {
- ConnectionInputPtr aci = AvailableInput->input;
- if (aci->size > BUFWATERMARK)
- {
- xfree(aci->buffer);
- xfree(aci);
- }
- else
- {
- aci->next = FreeInputs;
- FreeInputs = aci;
- }
- AvailableInput->input = (ConnectionInputPtr)NULL;
- }
- AvailableInput = (OsCommPtr)NULL;
- }
- if (!oci)
- {
- if ((oci = FreeInputs))
- FreeInputs = oci->next;
- else if (!(oci = AllocateInputBuffer()))
- return FALSE;
- oc->input = oci;
- }
- oci->bufptr += oci->lenLastReq;
- oci->lenLastReq = 0;
- gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
- if ((gotnow + count) > oci->size)
- {
- char *ibuf;
-
- ibuf = (char *)xrealloc(oci->buffer, gotnow + count);
- if (!ibuf)
- return(FALSE);
- oci->size = gotnow + count;
- oci->buffer = ibuf;
- oci->bufptr = ibuf + oci->bufcnt - gotnow;
- }
- moveup = count - (oci->bufptr - oci->buffer);
- if (moveup > 0)
- {
- if (gotnow > 0)
- memmove(oci->bufptr + moveup, oci->bufptr, gotnow);
- oci->bufptr += moveup;
- oci->bufcnt += moveup;
- }
- memmove(oci->bufptr - count, data, count);
- oci->bufptr -= count;
- gotnow += count;
- if ((gotnow >= sizeof(xReq)) &&
- (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2)))
- FD_SET(fd, &ClientsWithInput);
- else
- YieldControlNoInput();
- return(TRUE);
-}
-
-/*****************************************************************
- * ResetRequestFromClient
- * Reset to reexecute the current request, and yield.
- *
- **********************/
-
-void
-ResetCurrentRequest(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- register ConnectionInputPtr oci = oc->input;
- int fd = oc->fd;
- register xReq *request;
- int gotnow, needed;
-#ifdef LBX
- LbxClientPtr lbxClient = LbxClient(client);
-
- if (lbxClient) {
- LbxSetForBlock(lbxClient);
- if (!oci) {
- AppendFakeRequest(client,
- client->requestBuffer, client->req_len << 2);
- return;
- }
- }
-#endif
- if (AvailableInput == oc)
- AvailableInput = (OsCommPtr)NULL;
- oci->lenLastReq = 0;
- gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
- if (gotnow < sizeof(xReq))
- {
- YieldControlNoInput();
- }
- else
- {
- request = (xReq *)oci->bufptr;
- needed = get_req_len(request, client);
-#ifdef BIGREQS
- if (!needed && client->big_requests)
- {
- oci->bufptr -= sizeof(xBigReq) - sizeof(xReq);
- *(xReq *)oci->bufptr = *request;
- ((xBigReq *)oci->bufptr)->length = client->req_len;
- if (client->swapped)
- {
- char n;
- swapl(&((xBigReq *)oci->bufptr)->length, n);
- }
- }
-#endif
- if (gotnow >= (needed << 2))
- {
- if (FD_ISSET(fd, &AllClients))
- {
- FD_SET(fd, &ClientsWithInput);
- }
- else
- {
- FD_SET(fd, &IgnoredClientsWithInput);
- }
- YieldControl();
- }
- else
- YieldControlNoInput();
- }
-}
-
-
-
-/*****************************************************************
- * PeekNextRequest and SkipRequests were implemented to support DBE
- * idioms, but can certainly be used outside of DBE. There are two
- * related macros in os.h, ReqLen and CastxReq. See the porting
- * layer document for more details.
- *
- **********************/
-
-
-/*****************************************************************
- * PeekNextRequest
- * lets you look ahead at the unexecuted requests in a
- * client's request buffer.
- *
- * Note: this implementation of PeekNextRequest ignores the
- * readmore parameter.
- *
- **********************/
-
-xReqPtr
-PeekNextRequest(
- xReqPtr req, /* request we're starting from */
- ClientPtr client, /* client whose requests we're skipping */
- Bool readmore) /* attempt to read more if next request isn't there? */
-{
- register ConnectionInputPtr oci = ((OsCommPtr)client->osPrivate)->input;
- xReqPtr pnextreq;
- int needed, gotnow, reqlen;
-
- if (!oci) return NULL;
-
- if (!req)
- {
- /* caller wants the request after the one currently being executed */
- pnextreq = (xReqPtr)
- (((CARD32 *)client->requestBuffer) + client->req_len);
- }
- else
- {
- /* caller wants the request after the one specified by req */
- reqlen = get_req_len(req, client);
-#ifdef BIGREQS
- if (!reqlen) reqlen = get_big_req_len(req, client);
-#endif
- pnextreq = (xReqPtr)(((char *)req) + (reqlen << 2));
- }
-
- /* see how much of the next request we have available */
-
- gotnow = oci->bufcnt - (((char *)pnextreq) - oci->buffer);
-
- if (gotnow < sizeof(xReq))
- return NULL;
-
- needed = get_req_len(pnextreq, client) << 2;
-#ifdef BIGREQS
- if (!needed)
- {
- /* it's a big request */
- if (gotnow < sizeof(xBigReq))
- return NULL;
- needed = get_big_req_len(pnextreq, client) << 2;
- }
-#endif
-
- /* if we have less than we need, return NULL */
-
- return (gotnow < needed) ? NULL : pnextreq;
-}
-
-/*****************************************************************
- * SkipRequests
- * lets you skip over some of the requests in a client's
- * request buffer. Presumably the caller has used PeekNextRequest
- * to examine the requests being skipped and has performed whatever
- * actions they dictate.
- *
- **********************/
-
-CallbackListPtr SkippedRequestsCallback = NULL;
-
-void
-SkipRequests(
- xReqPtr req, /* last request being skipped */
- ClientPtr client, /* client whose requests we're skipping */
- int numskipped) /* how many requests we're skipping */
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- register ConnectionInputPtr oci = oc->input;
- int reqlen;
-
- /* see if anyone wants to snoop the skipped requests */
-
- if (SkippedRequestsCallback)
- {
- SkippedRequestInfoRec skipinfo;
- skipinfo.req = req;
- skipinfo.client = client;
- skipinfo.numskipped = numskipped;
- CallCallbacks(&SkippedRequestsCallback, &skipinfo);
- }
-
- /* adjust the sequence number */
- client->sequence += numskipped;
-
- /* twiddle the oci to skip over the requests */
-
- reqlen = get_req_len(req, client);
-#ifdef BIGREQS
- if (!reqlen) reqlen = get_big_req_len(req, client);
-#endif
- reqlen <<= 2;
- oci->bufptr = (char *)req;
- oci->lenLastReq = reqlen;
-
- /* see if any requests left in the buffer */
-
- if ( ((char *)req + reqlen) == (oci->buffer + oci->bufcnt) )
- {
- /* no requests; mark input buffer as available and client
- * as having no input
- */
- int fd = oc->fd;
- AvailableInput = oc;
- YieldControlNoInput();
- }
-}
-
-
- /* lookup table for adding padding bytes to data that is read from
- or written to the X socket. */
-static int padlength[4] = {0, 3, 2, 1};
-
- /********************
- * FlushAllOutput()
- * Flush all clients with output. However, if some client still
- * has input in the queue (more requests), then don't flush. This
- * will prevent the output queue from being flushed every time around
- * the round robin queue. Now, some say that it SHOULD be flushed
- * every time around, but...
- *
- **********************/
-
-void
-FlushAllOutput(void)
-{
- register int index, base;
- register fd_mask mask; /* raphael */
- OsCommPtr oc;
- register ClientPtr client;
- Bool newoutput = NewOutputPending;
-#if defined(WIN32)
- fd_set newOutputPending;
-#endif
-
- if (FlushCallback)
- CallCallbacks(&FlushCallback, NULL);
-
- if (!newoutput)
- return;
-
- /*
- * It may be that some client still has critical output pending,
- * but he is not yet ready to receive it anyway, so we will
- * simply wait for the select to tell us when he's ready to receive.
- */
- CriticalOutputPending = FALSE;
- NewOutputPending = FALSE;
-
-#ifndef WIN32
- for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++)
- {
- mask = OutputPending.fds_bits[ base ];
- OutputPending.fds_bits[ base ] = 0;
- while (mask)
- {
- index = ffs(mask) - 1;
- mask &= ~lowbit(mask);
- if ((index = ConnectionTranslation[(base * (sizeof(fd_mask)*8)) + index]) == 0)
- continue;
- client = clients[index];
- if (client->clientGone)
- continue;
- oc = (OsCommPtr)client->osPrivate;
- if (
-#ifdef LBX
- !oc->proxy &&
-#endif
- FD_ISSET(oc->fd, &ClientsWithInput))
- {
- FD_SET(oc->fd, &OutputPending); /* set the bit again */
- NewOutputPending = TRUE;
- }
- else
- (void)FlushClient(client, oc, (char *)NULL, 0);
- }
- }
-#else /* WIN32 */
- FD_ZERO(&newOutputPending);
- for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++)
- {
- index = XFD_FD(&OutputPending, base);
- if ((index = ConnectionTranslation[index]) == 0)
- continue;
- client = clients[index];
- if (client->clientGone)
- continue;
- oc = (OsCommPtr)client->osPrivate;
- if (
-#ifdef LBX
- !oc->proxy &&
-#endif
- FD_ISSET(oc->fd, &ClientsWithInput))
- {
- FD_SET(oc->fd, &newOutputPending); /* set the bit again */
- NewOutputPending = TRUE;
- }
- else
- (void)FlushClient(client, oc, (char *)NULL, 0);
- }
- XFD_COPYSET(&newOutputPending, &OutputPending);
-#endif /* WIN32 */
-}
-
-void
-FlushIfCriticalOutputPending(void)
-{
- if (CriticalOutputPending)
- FlushAllOutput();
-}
-
-void
-SetCriticalOutputPending(void)
-{
- CriticalOutputPending = TRUE;
-}
-
-/*****************
- * WriteToClient
- * Copies buf into ClientPtr.buf if it fits (with padding), else
- * flushes ClientPtr.buf and buf to client. As of this writing,
- * every use of WriteToClient is cast to void, and the result
- * is ignored. Potentially, this could be used by requests
- * that are sending several chunks of data and want to break
- * out of a loop on error. Thus, we will leave the type of
- * this routine as int.
- *****************/
-
-int
-WriteToClient (ClientPtr who, int count, char *buf)
-{
- OsCommPtr oc = (OsCommPtr)who->osPrivate;
- ConnectionOutputPtr oco = oc->output;
- int padBytes;
-#ifdef DEBUG_COMMUNICATION
- Bool multicount = FALSE;
-#endif
- if (!count)
- return(0);
-#ifdef DEBUG_COMMUNICATION
- {
- char info[128];
- xError *err;
- xGenericReply *rep;
- xEvent *ev;
-
- if (!who->replyBytesRemaining) {
- switch(buf[0]) {
- case X_Reply:
- rep = (xGenericReply*)buf;
- if (rep->sequenceNumber == who->sequence) {
- snprintf(info,127,"Xreply: type: 0x%x data: 0x%x "
- "len: %i seq#: 0x%x", rep->type, rep->data1,
- rep->length, rep->sequenceNumber);
- multicount = TRUE;
- }
- break;
- case X_Error:
- err = (xError*)buf;
- snprintf(info,127,"Xerror: Code: 0x%x resID: 0x%x maj: 0x%x "
- "min: %x", err->errorCode,err->resourceID,
- err->minorCode,err->majorCode);
- break;
- default:
- if ((buf[0] & 0x7f) == KeymapNotify)
- snprintf(info,127,"KeymapNotifyEvent: %i",buf[0]);
- else {
- ev = (xEvent*)buf;
- snprintf(info,127,"XEvent: type: 0x%x detail: 0x%x "
- "seq#: 0x%x", ev->u.u.type, ev->u.u.detail,
- ev->u.u.sequenceNumber);
- }
- }
- ErrorF("REPLY: ClientIDX: %i %s\n",who->index, info);
- } else
- multicount = TRUE;
- }
-#endif
-
- if (!oco)
- {
- if ((oco = FreeOutputs))
- {
- FreeOutputs = oco->next;
- }
- else if (!(oco = AllocateOutputBuffer()))
- {
- if (oc->trans_conn) {
- _XSERVTransDisconnect(oc->trans_conn);
- _XSERVTransClose(oc->trans_conn);
- oc->trans_conn = NULL;
- }
- MarkClientException(who);
- return -1;
- }
- oc->output = oco;
- }
-
- padBytes = padlength[count & 3];
-
- if(ReplyCallback)
- {
- ReplyInfoRec replyinfo;
-
- replyinfo.client = who;
- replyinfo.replyData = buf;
- replyinfo.dataLenBytes = count + padBytes;
- if (who->replyBytesRemaining)
- { /* still sending data of an earlier reply */
- who->replyBytesRemaining -= count + padBytes;
- replyinfo.startOfReply = FALSE;
- replyinfo.bytesRemaining = who->replyBytesRemaining;
- CallCallbacks((&ReplyCallback), (pointer)&replyinfo);
- }
- else if (who->clientState == ClientStateRunning
- && buf[0] == X_Reply)
- { /* start of new reply */
- CARD32 replylen;
- unsigned long bytesleft;
- char n;
-
- replylen = ((xGenericReply *)buf)->length;
- if (who->swapped)
- swapl(&replylen, n);
- bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes;
- replyinfo.startOfReply = TRUE;
- replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft;
- CallCallbacks((&ReplyCallback), (pointer)&replyinfo);
- }
- }
-#ifdef DEBUG_COMMUNICATION
- else if (multicount) {
- if (who->replyBytesRemaining) {
- who->replyBytesRemaining -= (count + padBytes);
- } else {
- CARD32 replylen;
- replylen = ((xGenericReply *)buf)->length;
- who->replyBytesRemaining =
- (replylen * 4) + SIZEOF(xReply) - count - padBytes;
- }
- }
-#endif
- if (oco->count + count + padBytes > oco->size)
- {
- FD_CLR(oc->fd, &OutputPending);
- if(!XFD_ANYSET(&OutputPending)) {
- CriticalOutputPending = FALSE;
- NewOutputPending = FALSE;
- }
- return FlushClient(who, oc, buf, count);
- }
-
- NewOutputPending = TRUE;
- FD_SET(oc->fd, &OutputPending);
- memmove((char *)oco->buf + oco->count, buf, count);
- oco->count += count + padBytes;
- return(count);
-}
-
- /********************
- * FlushClient()
- * If the client isn't keeping up with us, then we try to continue
- * buffering the data and set the apropriate bit in ClientsWritable
- * (which is used by WaitFor in the select). If the connection yields
- * a permanent error, or we can't allocate any more space, we then
- * close the connection.
- *
- **********************/
-
-#ifdef LBX
-#ifdef LBX_NEED_OLD_SYMBOL_FOR_LOADABLES
-#undef FlushClient
-int
-FlushClient(ClientPtr who, OsCommPtr oc, char *extraBuf, int extraCount)
-{
- return (*oc->Flush)(who, oc, extraBuf, extraCount);
-}
-#endif
-int
-StandardFlushClient(ClientPtr who, OsCommPtr oc,
- char *extraBuf, int extraCount)
-#else
-int
-FlushClient(ClientPtr who, OsCommPtr oc, char *extraBuf, int extraCount)
-#endif
-{
- ConnectionOutputPtr oco = oc->output;
- int connection = oc->fd;
- XtransConnInfo trans_conn = oc->trans_conn;
- struct iovec iov[3];
- static char padBuffer[3];
- long written;
- long padsize;
- long notWritten;
- long todo;
-
- if (!oco)
- return 0;
- written = 0;
- padsize = padlength[extraCount & 3];
- notWritten = oco->count + extraCount + padsize;
- todo = notWritten;
- while (notWritten) {
- long before = written; /* amount of whole thing written */
- long remain = todo; /* amount to try this time, <= notWritten */
- int i = 0;
- long len;
-
- /* You could be very general here and have "in" and "out" iovecs
- * and write a loop without using a macro, but what the heck. This
- * translates to:
- *
- * how much of this piece is new?
- * if more new then we are trying this time, clamp
- * if nothing new
- * then bump down amount already written, for next piece
- * else put new stuff in iovec, will need all of next piece
- *
- * Note that todo had better be at least 1 or else we'll end up
- * writing 0 iovecs.
- */
-#define InsertIOV(pointer, length) \
- len = (length) - before; \
- if (len > remain) \
- len = remain; \
- if (len <= 0) { \
- before = (-len); \
- } else { \
- iov[i].iov_len = len; \
- iov[i].iov_base = (pointer) + before; \
- i++; \
- remain -= len; \
- before = 0; \
- }
-
- InsertIOV ((char *)oco->buf, oco->count)
- InsertIOV (extraBuf, extraCount)
- InsertIOV (padBuffer, padsize)
-
- errno = 0;
- if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0)
- {
- written += len;
- notWritten -= len;
- todo = notWritten;
- }
- else if (ETEST(errno)
-#ifdef SUNSYSV /* check for another brain-damaged OS bug */
- || (errno == 0)
-#endif
-#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
- || ((errno == EMSGSIZE) && (todo == 1))
-#endif
- )
- {
- /* If we've arrived here, then the client is stuffed to the gills
- and not ready to accept more. Make a note of it and buffer
- the rest. */
- FD_SET(connection, &ClientsWriteBlocked);
- AnyClientsWriteBlocked = TRUE;
-
- if (written < oco->count)
- {
- if (written > 0)
- {
- oco->count -= written;
- memmove((char *)oco->buf,
- (char *)oco->buf + written,
- oco->count);
- written = 0;
- }
- }
- else
- {
- written -= oco->count;
- oco->count = 0;
- }
-
- if (notWritten > oco->size)
- {
- unsigned char *obuf;
-
- obuf = (unsigned char *)xrealloc(oco->buf,
- notWritten + BUFSIZE);
- if (!obuf)
- {
- _XSERVTransDisconnect(oc->trans_conn);
- _XSERVTransClose(oc->trans_conn);
- oc->trans_conn = NULL;
- MarkClientException(who);
- oco->count = 0;
- return(-1);
- }
- oco->size = notWritten + BUFSIZE;
- oco->buf = obuf;
- }
-
- /* If the amount written extended into the padBuffer, then the
- difference "extraCount - written" may be less than 0 */
- if ((len = extraCount - written) > 0)
- memmove ((char *)oco->buf + oco->count,
- extraBuf + written,
- len);
-
- oco->count = notWritten; /* this will include the pad */
- /* return only the amount explicitly requested */
- return extraCount;
- }
-#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
- else if (errno == EMSGSIZE)
- {
- todo >>= 1;
- }
-#endif
- else
- {
- if (oc->trans_conn)
- {
- _XSERVTransDisconnect(oc->trans_conn);
- _XSERVTransClose(oc->trans_conn);
- oc->trans_conn = NULL;
- }
- MarkClientException(who);
- oco->count = 0;
- return(-1);
- }
- }
-
- /* everything was flushed out */
- oco->count = 0;
- /* check to see if this client was write blocked */
- if (AnyClientsWriteBlocked)
- {
- FD_CLR(oc->fd, &ClientsWriteBlocked);
- if (! XFD_ANYSET(&ClientsWriteBlocked))
- AnyClientsWriteBlocked = FALSE;
- }
- if (oco->size > BUFWATERMARK)
- {
- xfree(oco->buf);
- xfree(oco);
- }
- else
- {
- oco->next = FreeOutputs;
- FreeOutputs = oco;
- }
- oc->output = (ConnectionOutputPtr)NULL;
- return extraCount; /* return only the amount explicitly requested */
-}
-
-ConnectionInputPtr
-AllocateInputBuffer(void)
-{
- ConnectionInputPtr oci;
-
- oci = (ConnectionInputPtr)xalloc(sizeof(ConnectionInput));
- if (!oci)
- return (ConnectionInputPtr)NULL;
- oci->buffer = (char *)xalloc(BUFSIZE);
- if (!oci->buffer)
- {
- xfree(oci);
- return (ConnectionInputPtr)NULL;
- }
- oci->size = BUFSIZE;
- oci->bufptr = oci->buffer;
- oci->bufcnt = 0;
- oci->lenLastReq = 0;
- return oci;
-}
-
-ConnectionOutputPtr
-AllocateOutputBuffer(void)
-{
- ConnectionOutputPtr oco;
-
- oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput));
- if (!oco)
- return (ConnectionOutputPtr)NULL;
- oco->buf = (unsigned char *) xalloc(BUFSIZE);
- if (!oco->buf)
- {
- xfree(oco);
- return (ConnectionOutputPtr)NULL;
- }
- oco->size = BUFSIZE;
- oco->count = 0;
-#ifdef LBX
- oco->nocompress = FALSE;
-#endif
- return oco;
-}
-
-void
-FreeOsBuffers(OsCommPtr oc)
-{
- ConnectionInputPtr oci;
- ConnectionOutputPtr oco;
-
- if (AvailableInput == oc)
- AvailableInput = (OsCommPtr)NULL;
- if ((oci = oc->input))
- {
- if (FreeInputs)
- {
- xfree(oci->buffer);
- xfree(oci);
- }
- else
- {
- FreeInputs = oci;
- oci->next = (ConnectionInputPtr)NULL;
- oci->bufptr = oci->buffer;
- oci->bufcnt = 0;
- oci->lenLastReq = 0;
- }
- }
- if ((oco = oc->output))
- {
- if (FreeOutputs)
- {
- xfree(oco->buf);
- xfree(oco);
- }
- else
- {
- FreeOutputs = oco;
- oco->next = (ConnectionOutputPtr)NULL;
- oco->count = 0;
- }
- }
-#ifdef LBX
- if ((oci = oc->largereq)) {
- xfree(oci->buffer);
- xfree(oci);
- }
-#endif
-}
-
-void
-ResetOsBuffers(void)
-{
- ConnectionInputPtr oci;
- ConnectionOutputPtr oco;
-
- while ((oci = FreeInputs))
- {
- FreeInputs = oci->next;
- xfree(oci->buffer);
- xfree(oci);
- }
- while ((oco = FreeOutputs))
- {
- FreeOutputs = oco->next;
- xfree(oco->buf);
- xfree(oco);
- }
-}