X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=Xserver%2Fprograms%2FXserver%2Fos%2Fio.c;fp=Xserver%2Fprograms%2FXserver%2Fos%2Fio.c;h=0000000000000000000000000000000000000000;hb=ce66b81460e5353db09d45c02339d4583fbda255;hp=9f5ea5c12523eae90bf4fb3c5158d97d90ad6aab;hpb=7772d71ffd742cfc9b7ff214659d16c5bb56a391;p=rdpsrv diff --git a/Xserver/programs/Xserver/os/io.c b/Xserver/programs/Xserver/os/io.c deleted file mode 100644 index 9f5ea5c..0000000 --- a/Xserver/programs/Xserver/os/io.c +++ /dev/null @@ -1,1259 +0,0 @@ -/*********************************************************** - -Copyright (c) 1987, 1989 X Consortium - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -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 -X CONSORTIUM 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 X Consortium 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 X Consortium. - - -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. - -******************************************************************/ -/* $XConsortium: io.c /main/72 1996/12/27 15:40:56 rws $ */ -/* $XFree86: xc/programs/Xserver/os/io.c,v 3.15 1997/01/18 06:58:00 dawes Exp $ */ -/***************************************************************** - * i/o functions - * - * WriteToClient, ReadRequestFromClient - * InsertFakeRequest, ResetCurrentRequest - * - *****************************************************************/ - -#ifdef WIN32 -#include -#endif -#include -#include -#ifdef X_NOT_STDC_ENV -extern int errno; -#endif -#include "Xmd.h" -#include -#if !defined(AMOEBA) && !defined(MINIX) && !defined(__EMX__) && !defined(WIN32) -#ifndef Lynx -#include -#else -#include -#endif -#endif -#include "X.h" -#define NEED_REPLIES -#include "Xproto.h" -#include "os.h" -#include "Xpoll.h" -#include "osdep.h" -#include "opaque.h" -#include "dixstruct.h" -#include "misc.h" -#ifdef LBX -#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 __EMX__ -#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 /* __EMX__ Writing to full pipes may return ENOSPC */ -#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK || err == ENOSPC) -#endif - -extern fd_set ClientsWithInput, IgnoredClientsWithInput, AllClients; -extern fd_set ClientsWriteBlocked; -extern fd_set OutputPending; -extern int ConnectionTranslation[]; -extern Bool NewOutputPending; -extern Bool AnyClientsWriteBlocked; - -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; } - -#if defined(LBX) || defined(LBX_COMPAT) -int -StandardReadRequestFromClient(client) - ClientPtr client; -#else -int -ReadRequestFromClient(client) - ClientPtr client; -#endif -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - register ConnectionInputPtr oci = oc->input; - int fd = oc->fd; - register 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 - YieldControlNoInput(); - } - else - { - if (!gotnow) - AvailableInput = oc; - YieldControlNoInput(); - } - 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; - return needed; -} - -/***************************************************************** - * InsertFakeRequest - * Splice a consed up (possibly partial) request in as the next request. - * - **********************/ - -Bool -InsertFakeRequest(client, data, count) - ClientPtr client; - char *data; - int count; -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - register ConnectionInputPtr oci = oc->input; - int fd = oc->fd; - register int gotnow, moveup; - - 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; - } - 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. - * - **********************/ - -ResetCurrentRequest(client) - ClientPtr client; -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - register ConnectionInputPtr oci = oc->input; - int fd = oc->fd; - register xReq *request; - int gotnow, needed; -#ifdef LBX - Bool part; - 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(req, client, readmore) - 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(req, client, numskipped) - 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}; - - /******************** - * 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. - * - **********************/ - -int -#ifdef LBX -StandardFlushClient(who, oc, extraBuf, extraCount) -#else -FlushClient(who, oc, extraBuf, extraCount) -#endif - ClientPtr who; - OsCommPtr oc; - char *extraBuf; - int extraCount; /* do not modify... returned below */ -{ - register 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 */ -} - - /******************** - * 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() -{ - register int index, base, mask; - OsCommPtr oc; - register ClientPtr client; - Bool newoutput = NewOutputPending; -#ifdef 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 << 5) + 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() -{ - if (CriticalOutputPending) - FlushAllOutput(); -} - -void -SetCriticalOutputPending() -{ - 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 (who, count, buf) - ClientPtr who; - char *buf; - int count; -{ - OsCommPtr oc = (OsCommPtr)who->osPrivate; - register ConnectionOutputPtr oco = oc->output; - int padBytes; - - if (!count) - return(0); - - 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); - } - } - - if (oco->count + count + padBytes > oco->size) - { - FD_CLR(oc->fd, &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); -} - -ConnectionInputPtr -AllocateInputBuffer() -{ - register 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() -{ - register 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(oc) - OsCommPtr oc; -{ - register ConnectionInputPtr oci; - register 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() -{ - register ConnectionInputPtr oci; - register ConnectionOutputPtr oco; - - while (oci = FreeInputs) - { - FreeInputs = oci->next; - xfree(oci->buffer); - xfree(oci); - } - while (oco = FreeOutputs) - { - FreeOutputs = oco->next; - xfree(oco->buf); - xfree(oco); - } -}