Annotation of researchv9/X11/src/X.V11R1/server/os/v9/io.c, revision 1.1

1.1     ! root        1: /***********************************************************
        !             2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
        !             3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
        !             4: 
        !             5:                         All Rights Reserved
        !             6: 
        !             7: Permission to use, copy, modify, and distribute this software and its 
        !             8: documentation for any purpose and without fee is hereby granted, 
        !             9: provided that the above copyright notice appear in all copies and that
        !            10: both that copyright notice and this permission notice appear in 
        !            11: supporting documentation, and that the names of Digital or MIT not be
        !            12: used in advertising or publicity pertaining to distribution of the
        !            13: software without specific, written prior permission.  
        !            14: 
        !            15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            21: SOFTWARE.
        !            22: 
        !            23: ******************************************************************/
        !            24: /* $Header: io.c,v 1.36 87/09/09 23:04:35 rws Exp $ */
        !            25: /*****************************************************************
        !            26:  * i/o functions
        !            27:  *
        !            28:  *   WriteToClient, ReadRequestFromClient
        !            29:  *
        !            30:  *****************************************************************/
        !            31: 
        !            32: #include <stdio.h>
        !            33: #include "Xmd.h"
        !            34: #include <errno.h>
        !            35: #include <sys/param.h>
        !            36: #include <sys/types.h>
        !            37: #include "X.h"
        !            38: #include "Xproto.h"
        !            39: #include "os.h"
        !            40: #include "osdep.h"
        !            41: #include "opaque.h"
        !            42: #include "dixstruct.h"
        !            43: 
        !            44: extern long ClientsWithInput[];
        !            45: extern long PartialRequest;
        !            46: extern ClientPtr ConnectionTranslation[];
        !            47: static int timesThisConnection = 0;
        !            48: 
        !            49: extern int errno;
        !            50: 
        !            51: #define request_length(req, cli) ((cli->swapped ? \
        !            52:        lswaps((req)->length) : (req)->length) << 2)
        !            53: #define MAX_TIMES_PER         10
        !            54: 
        !            55: /*****************************************************************
        !            56:  * ReadRequestFromClient
        !            57:  *    Returns one request from client.  If the client misbehaves,
        !            58:  *    returns NULL.  The dispatcher closes down all misbehaving clients.  
        !            59:  *
        !            60:  *        client:  index into bit array returned from WaitForSomething() 
        !            61:  *
        !            62:  *        status: status is set to
        !            63:  *            > 0 the number of bytes in the request if the read is sucessful 
        !            64:  *            = 0 if action would block (entire request not ready)
        !            65:  *            < 0 indicates an error (probably client died)
        !            66:  *
        !            67:  *        oldbuf:
        !            68:  *            To facilitate buffer management (e.g. on multi-processor
        !            69:  *            systems), the diX layer must tell the OS layer when it is 
        !            70:  *            done with a request, so the parameter oldbuf is a pointer 
        !            71:  *            to a request that diX is finished with.  In the 
        !            72:  *            sample implementation, which is single threaded,
        !            73:  *            oldbuf is ignored.  We assume that when diX calls
        !            74:  *            ReadRequestFromClient(), the previous buffer is finished with.
        !            75:  *
        !            76:  *    The returned string returned must be contiguous so that it can be
        !            77:  *    cast in the dispatcher to the correct request type.  Because requests
        !            78:  *    are variable length, ReadRequestFromClient() must look at the first 4
        !            79:  *    bytes of a request to determine the length (the request length is
        !            80:  *    always the 3rd byte in the request).  
        !            81:  *
        !            82:  *    Note: in order to make the server scheduler (WaitForSomething())
        !            83:  *    "fair", the ClientsWithInput mask is used.  This mask tells which
        !            84:  *    clients have FULL requests left in their buffers.  Clients with
        !            85:  *    partial requests require a read.  Basically, client buffers
        !            86:  *    are drained before select() is called again.  But, we can't keep
        !            87:  *    reading from a client that is sending buckets of data (or has
        !            88:  *    a partial request) because others clients need to be scheduled.
        !            89:  *****************************************************************/
        !            90: 
        !            91: ConnectionInput inputBuffers[MAXSOCKS];    /* buffers for clients */
        !            92: 
        !            93: char *
        !            94: ReadRequestFromClient(who, status, oldbuf)
        !            95:     ClientPtr who;
        !            96:     int *status;          /* read at least n from client */
        !            97:     char *oldbuf;
        !            98: {
        !            99:     int client = ((osPrivPtr)who->osPrivate)->fd;
        !           100:     int result, gotnow, needed;
        !           101:     register ConnectionInput *pBuff;
        !           102:     register xReq *request;
        !           103: 
        !           104:         /* ignore oldbuf, just assume we're done with prev. buffer */
        !           105: 
        !           106:     if (client == -1) 
        !           107:     {
        !           108:        ErrorF( "OH NO, %d translates to -1\n", who);
        !           109:        return((char *)NULL);
        !           110:     }
        !           111: 
        !           112:     pBuff = &inputBuffers[client];
        !           113:     pBuff->bufptr += pBuff->lenLastReq;
        !           114:     pBuff->lenLastReq = 0;
        !           115: 
        !           116:             /* handle buffer empty or full case first */
        !           117: 
        !           118:     if ((pBuff->bufptr - pBuff->buffer >= pBuff->bufcnt) || (!pBuff->bufcnt))
        !           119:     {
        !           120:         result = read(client, pBuff->buffer, pBuff->size);
        !           121:        if (result <= 0) 
        !           122:        {
        !           123:            *status = -1;
        !           124:            BITCLEAR(ClientsWithInput, client);
        !           125:            isItTimeToYield = TRUE;
        !           126:            return((char *)NULL);
        !           127:        }
        !           128:        else 
        !           129:        {
        !           130:            pBuff->bufcnt = result; 
        !           131:            pBuff->bufptr = pBuff->buffer;
        !           132:        }
        !           133:     }
        !           134:               /* now look if there is enough in the buffer */
        !           135: 
        !           136:     request = (xReq *)pBuff->bufptr;
        !           137:     gotnow = pBuff->bufcnt + pBuff->buffer - pBuff->bufptr;
        !           138: 
        !           139:     if (gotnow < sizeof(xReq))
        !           140:        needed = sizeof(xReq) - gotnow;
        !           141:     else
        !           142:     {
        !           143:         needed = request_length(request, who);
        !           144:         if (needed > MAXBUFSIZE)
        !           145:         {
        !           146:            *status = -1;
        !           147:            BITCLEAR(ClientsWithInput, client);
        !           148:            isItTimeToYield = TRUE;
        !           149:            return((char *)NULL);
        !           150:         }
        !           151:        if (needed <= 0)
        !           152:             needed = sizeof(xReq);
        !           153:     }
        !           154:         /* if the needed amount won't fit in what's remaining,
        !           155:           move everything to the front of the buffer.  If the
        !           156:           entire header isn't available, move what's there too */
        !           157:     if ((pBuff->bufptr + needed - pBuff->buffer > pBuff->size) ||
        !           158:                (gotnow < sizeof(xReq)))
        !           159:     {
        !           160:         bcopy(pBuff->bufptr, pBuff->buffer, gotnow);
        !           161:        pBuff->bufcnt = gotnow;
        !           162:         if (needed > pBuff->size)
        !           163:         {
        !           164:            pBuff->size = needed;
        !           165:            pBuff->buffer = (char *)Xrealloc(pBuff->buffer, needed);
        !           166:         }
        !           167:         pBuff->bufptr = pBuff->buffer;
        !           168:     }
        !           169:                /* don't have a full header */
        !           170:     if (gotnow < sizeof(xReq))
        !           171:     {
        !           172:         while (pBuff->bufcnt + pBuff->buffer - pBuff->bufptr < sizeof(xReq))
        !           173:        {
        !           174:            result = read(client, pBuff->buffer + pBuff->bufcnt, 
        !           175:                      pBuff->size - pBuff->bufcnt); 
        !           176:            if (result <= 0)
        !           177:            {
        !           178:                *status = -1;
        !           179:                BITCLEAR(ClientsWithInput, client);
        !           180:                isItTimeToYield = TRUE;
        !           181:                return((char *)NULL);
        !           182:            }
        !           183:             pBuff->bufcnt += result;        
        !           184:        }
        !           185:         request = (xReq *)pBuff->bufptr;
        !           186:         gotnow = pBuff->bufcnt + pBuff->buffer - pBuff->bufptr;
        !           187:         needed = request_length(request, who);
        !           188:        if (needed <= 0)
        !           189:             needed = sizeof(xReq);
        !           190:         if (needed > pBuff->size)
        !           191:         {
        !           192:            pBuff->size = needed;
        !           193:            pBuff->buffer = (char *)Xrealloc(pBuff->buffer, needed);
        !           194:         }
        !           195:         pBuff->bufptr = pBuff->buffer;
        !           196:     }  
        !           197: 
        !           198:     if (gotnow < needed )   
        !           199:     {
        !           200:        int i, wanted;
        !           201: 
        !           202:        wanted = needed - gotnow;
        !           203:        i = 0;
        !           204:        while (i < wanted) 
        !           205:        {
        !           206:            result = read(client, pBuff->buffer + pBuff->bufcnt, 
        !           207:                          pBuff->size - pBuff->bufcnt); 
        !           208:            if (result <= 0) { 
        !           209:                *status = -1;
        !           210:                BITCLEAR(ClientsWithInput, client);
        !           211:                isItTimeToYield = TRUE;
        !           212:                return((char *)NULL);
        !           213:            }
        !           214:            i += result;
        !           215:            pBuff->bufcnt += result;
        !           216:        }
        !           217:     }
        !           218:     *status = needed;
        !           219:     pBuff->lenLastReq = needed;
        !           220: 
        !           221:     /*
        !           222:      *  Check to see if client has at least one whole request in the
        !           223:      *  buffer.  If there is only a partial request, treat like buffer
        !           224:      *  is empty so that select() will be called again and other clients
        !           225:      *  can get into the queue.   
        !           226:      */
        !           227: 
        !           228:     if (pBuff->bufcnt + pBuff->buffer >= pBuff->bufptr + needed + sizeof(xReq)) 
        !           229:     {
        !           230:        request = (xReq *)(pBuff->bufptr + needed);
        !           231:         if ((pBuff->bufcnt + pBuff->buffer) >= 
        !           232:             ((char *)request + request_length(request, who)))
        !           233:            BITSET(ClientsWithInput, client);
        !           234:         else
        !           235:        {
        !           236:            BITCLEAR(ClientsWithInput, client);
        !           237:            isItTimeToYield = TRUE;
        !           238:        }
        !           239:     }
        !           240:     else
        !           241:     {
        !           242:         BITCLEAR(ClientsWithInput, client);
        !           243:        isItTimeToYield = TRUE;
        !           244:     }
        !           245:     if ((++timesThisConnection == MAX_TIMES_PER) || (isItTimeToYield))
        !           246:     {
        !           247:         isItTimeToYield = TRUE;
        !           248:         timesThisConnection = 0;
        !           249:     }
        !           250:     return((char *)pBuff->bufptr);
        !           251: }
        !           252: 
        !           253: 
        !           254: /*****************
        !           255:  * WriteToClient
        !           256:  *    We might have to wait, if the client isn't keeping up with us.  We 
        !           257:  *    wait for a short time, then close the connection.  This isn't a 
        !           258:  *    wonderful solution,
        !           259:  *    but it rarely seems to be a problem right now, and buffering output for
        !           260:  *    asynchronous delivery sounds complicated and expensive.
        !           261:  *    Long word aligns all data.
        !           262:  *    Makes assumption that at least three bytes after address given
        !           263:  *     are writeable (used for padding)
        !           264:  *****************/
        !           265: 
        !           266:     /* lookup table for adding padding bytes to data that is read from
        !           267:        or written to the X socket.  */
        !           268: static int padlength[4] = {0, 3, 2, 1};
        !           269: 
        !           270: int
        !           271: WriteToClient (who, cnt, buf)
        !           272:     ClientPtr who;
        !           273:     char *buf;
        !           274:     int cnt;
        !           275: {
        !           276: #define OUTTIME 2              
        !           277:     int connection = ((osPrivPtr)who->osPrivate)->fd;
        !           278:     register int n;
        !           279: 
        !           280:     if (connection == -1) 
        !           281:     {
        !           282:        ErrorF( "OH NO, %d translates to -1\n", connection);
        !           283:        return(-1);
        !           284:     }
        !           285: 
        !           286:     if (connection == -2) 
        !           287:     {
        !           288: #ifdef notdef
        !           289:        ErrorF( "CONNECTION %d ON ITS WAY OUT\n", connection);
        !           290: #endif
        !           291:        return(-1);
        !           292:     }
        !           293: 
        !           294:     n = write(connection, buf, cnt + padlength[cnt & 3]);
        !           295:     if (n < cnt) {
        !           296:        close(connection);
        !           297:        MarkClientException(who);
        !           298:        return(-1);
        !           299:     }
        !           300:     return(cnt);
        !           301: }
        !           302: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.