rem: return SOCK_READY;
add: return (reqPtr->request ? SOCK_READY : SOCK_ERROR);
context: SockRead(Sock *sockPtr){    Ns_Sock *sock = (Ns_Sock *) sockPtr;    NsServer *servPtr = sockPtr->drvPtr->servPtr;    Ns_Buf buf;    Request *reqPtr;    Tcl_DString *bufPtr;    char *s, *e, save;    int   cnt, len, nread, n;    reqPtr = sockPtr->reqPtr;    if (reqPtr == NULL) {	Ns_MutexLock(&reqLock);	reqPtr = firstReqPtr;	if (reqPtr != NULL) {	    firstReqPtr = reqPtr->nextPtr;	}	Ns_MutexUnlock(&reqLock);	if (reqPtr == NULL) {	    reqPtr = ns_malloc(sizeof(Request));	    Tcl_DStringInit(&reqPtr->buffer);	    reqPtr->headers = Ns_SetCreate(NULL);	    reqPtr->request = NULL;	    reqPtr->next = reqPtr->content = NULL;	    reqPtr->length = reqPtr->avail = 0;	    reqPtr->coff = reqPtr->woff = reqPtr->roff = 0;	}	sockPtr->reqPtr = reqPtr;    	reqPtr->port = ntohs(sockPtr->sa.sin_port);	strcpy(reqPtr->peer, ns_inet_ntoa(sockPtr->sa.sin_addr));    }    /*     * On the first read, attempt to read-ahead bufsize bytes.     * Otherwise, read only the number of bytes left in the     * content.     */    bufPtr = &reqPtr->buffer;    if (reqPtr->length == 0) {	nread = sockPtr->drvPtr->bufsize;    } else {	nread = reqPtr->length - reqPtr->avail;    }    /*     * Grow the buffer to include space for the next bytes.     */    len = bufPtr->length;    Tcl_DStringSetLength(bufPtr, len + nread);    buf.ns_buf = bufPtr->string + reqPtr->woff;    buf.ns_len = nread;    n = (*sockPtr->drvPtr->proc)(DriverRecv, sock, &buf, 1);    if (n <= 0) {	return SOCK_ERROR;    }    Tcl_DStringSetLength(bufPtr, len + n);    reqPtr->woff  += n;    reqPtr->avail += n;    /*     * Scan lines until start of content.     */    while (reqPtr->coff == 0) {	/*	 * Find the next line.	 */	s = bufPtr->string + reqPtr->roff;	e = strchr(s, '\n');	if (e == NULL) {	    /*	     * Input not yet null terminated - request more.	     */	    return SOCK_MORE;	}	/*	 * Update next read pointer to end of this line.	 */	cnt = e - s + 1;	reqPtr->roff  += cnt;	reqPtr->avail -= cnt;	if (e > s && e[-1] == '\r') {	    --e;	}	/*	 * Check for end of headers.	 */	if (e == s) {	    reqPtr->coff = reqPtr->roff;	    s = Ns_SetIGet(reqPtr->headers, "content-length");	    if (s != NULL) {		reqPtr->length = atoi(s);	    }	} else {	    save = *e;	    *e = '\0';	    if (reqPtr->request == NULL) {		reqPtr->request = Ns_ParseRequest(s);		if (reqPtr->request == NULL) {		    /*		     * Invalid request.		     */		    return SOCK_ERROR;		}	    } else if (Ns_ParseHeader(reqPtr->headers, s, servPtr->opts.hdrcase) != NS_OK) {		/*		 * Invalid header.		 */		return SOCK_ERROR;	    }	    *e = save;	    if (reqPtr->request->version <= 0.0) {		/*		 * Pre-HTTP/1.0 request.		 */		reqPtr->coff = reqPtr->roff;	    }	}    }    /*     * Check if all content has arrived.     */    if (reqPtr->coff > 0 && reqPtr->length <= reqPtr->avail) {	reqPtr->content = bufPtr->string + reqPtr->coff;	reqPtr->next = reqPtr->content;	reqPtr->avail = reqPtr->length;	return SOCK_READY;    }    /*     * Wait for more input.     */    return SOCK_MORE;}