📄 io.c
字号:
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... * **********************/voidFlushAllOutput(){ register int index, base; fd_mask 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 = ffsl(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 */}voidFlushIfCriticalOutputPending(){ if (CriticalOutputPending) FlushAllOutput();}voidSetCriticalOutputPending(){ 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. *****************/intWriteToClient (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);}ConnectionInputPtrAllocateInputBuffer(){ 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;}ConnectionOutputPtrAllocateOutputBuffer(){ 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;}voidFreeOsBuffers(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}voidResetOsBuffers(){ 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); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -