📄 io.c
字号:
#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. * **********************/BoolInsertFakeRequest(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. * **********************/xReqPtrPeekNextRequest(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;voidSkipRequests(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 LBXStandardFlushClient(who, oc, extraBuf, extraCount)#elseFlushClient(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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -