rv = PR_Read(ssl_sock, pBuf, bufRem);
rv = PR_Read(ssl_sock, pBuf, bufRem - 1);
handle_connection(     PRFileDesc *tcp_sock,    PRFileDesc *model_sock,    int         requestCert    ){    PRFileDesc *       ssl_sock = NULL;    PRFileDesc *       local_file_fd = NULL;    char  *            post;    char  *            pBuf;			/* unused space at end of buf */    const char *       errString;    PRStatus           status;    int                bufRem;			/* unused bytes at end of buf */    int                bufDat;			/* characters received in buf */    int                newln    = 0;		/* # of consecutive newlns */    int                firstTime = 1;    int                reqLen;    int                rv;    int                numIOVs;    PRSocketOptionData opt;    PRIOVec            iovs[16];    char               msgBuf[160];    char               buf[10240];    char               fileName[513];    pBuf   = buf;    bufRem = sizeof buf;    memset(buf, 0, sizeof buf);    VLOG(("selfserv: handle_connection: starting"));    opt.option             = PR_SockOpt_Nonblocking;    opt.value.non_blocking = PR_FALSE;    PR_SetSocketOption(tcp_sock, &opt);    VLOG(("selfserv: handle_connection: starting\n"));    if (useModelSocket && model_sock) {	SECStatus rv;	ssl_sock = SSL_ImportFD(model_sock, tcp_sock);	if (!ssl_sock) {	    errWarn("SSL_ImportFD with model");	    goto cleanup;	}	rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1);	if (rv != SECSuccess) {	    errWarn("SSL_ResetHandshake");	    goto cleanup;	}    } else {	ssl_sock = tcp_sock;    }    if (noDelay) {	opt.option         = PR_SockOpt_NoDelay;	opt.value.no_delay = PR_TRUE;	status = PR_SetSocketOption(ssl_sock, &opt);	if (status != PR_SUCCESS) {	    errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");            if (ssl_sock) {	        PR_Close(ssl_sock);            }	    return SECFailure;	}    }    while (1) {	newln = 0;	reqLen     = 0;	rv = PR_Read(ssl_sock, pBuf, bufRem);	if (rv == 0 || 	    (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) {	    if (verbose)		errWarn("HDX PR_Read hit EOF");	    break;	}	if (rv < 0) {	    errWarn("HDX PR_Read");	    goto cleanup;	}	if (firstTime) {	    firstTime = 0;	    printSecurityInfo(ssl_sock);	}	pBuf   += rv;	bufRem -= rv;	bufDat = pBuf - buf;	/* Parse the input, starting at the beginning of the buffer.	 * Stop when we detect two consecutive \n's (or \r\n's) 	 * as this signifies the end of the GET or POST portion.	 * The posted data follows.	 */	while (reqLen < bufDat && newln < 2) {	    int octet = buf[reqLen++];	    if (octet == '\n') {		newln++;	    } else if (octet != '\r') {		newln = 0;	    }	}	/* came to the end of the buffer, or second newln	 * If we didn't get an empty line (CRLFCRLF) then keep on reading.	 */	if (newln < 2) 	    continue;	/* we're at the end of the HTTP request.	 * If the request is a POST, then there will be one more	 * line of data.	 * This parsing is a hack, but ok for SSL test purposes.	 */	post = PORT_Strstr(buf, "POST ");	if (!post || *post != 'P') 	    break;	/* It's a post, so look for the next and final CR/LF. */	/* We should parse content length here, but ... */	while (reqLen < bufDat && newln < 3) {	    int octet = buf[reqLen++];	    if (octet == '\n') {		newln++;	    }	}	if (newln == 3)	    break;    } /* read loop */    bufDat = pBuf - buf;    if (bufDat) do {	/* just close if no data */	/* Have either (a) a complete get, (b) a complete post, (c) EOF */	if (reqLen > 0 && !strncmp(buf, getCmd, sizeof getCmd - 1)) {	    char *      fnBegin = buf + 4;	    char *      fnEnd;	    PRFileInfo  info;	    /* try to open the file named.  	     * If succesful, then write it to the client.	     */	    fnEnd = strpbrk(fnBegin, " \r\n");	    if (fnEnd) {		int fnLen = fnEnd - fnBegin;		if (fnLen < sizeof fileName) {		    strncpy(fileName, fnBegin, fnLen);		    fileName[fnLen] = 0;	/* null terminate */		    status = PR_GetFileInfo(fileName, &info);		    if (status == PR_SUCCESS &&			info.type == PR_FILE_FILE &&			info.size >= 0 ) {			local_file_fd = PR_Open(fileName, PR_RDONLY, 0);		    }		}	    }	}	/* if user has requested client auth in a subsequent handshake,	 * do it here.	 */	if (requestCert > 2) { /* request cert was 3 or 4 */	    CERTCertificate *  cert =  SSL_PeerCertificate(ssl_sock);	    if (cert) {		CERT_DestroyCertificate(cert);	    } else {		rv = SSL_OptionSet(ssl_sock, SSL_REQUEST_CERTIFICATE, 1);		if (rv < 0) {		    errWarn("second SSL_OptionSet SSL_REQUEST_CERTIFICATE");		    break;		}		rv = SSL_OptionSet(ssl_sock, SSL_REQUIRE_CERTIFICATE, 				(requestCert == 4));		if (rv < 0) {		    errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE");		    break;		}		rv = SSL_ReHandshake(ssl_sock, PR_TRUE);		if (rv != 0) {		    errWarn("SSL_ReHandshake");		    break;		}		rv = SSL_ForceHandshake(ssl_sock);		if (rv < 0) {		    errWarn("SSL_ForceHandshake");		    break;		}	    }	}	numIOVs = 0;	iovs[numIOVs].iov_base = (char *)outHeader;	iovs[numIOVs].iov_len  = (sizeof(outHeader)) - 1;	numIOVs++;	if (local_file_fd) {	    PRInt32     bytes;	    int         errLen;	    bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,				    sizeof outHeader - 1, 				    PR_TRANSMITFILE_KEEP_OPEN,				    PR_INTERVAL_NO_TIMEOUT);	    if (bytes >= 0) {		bytes -= sizeof outHeader - 1;		FPRINTF(stderr, 			"selfserv: PR_TransmitFile wrote %d bytes from %s\n",			bytes, fileName);		break;	    }	    errString = errWarn("PR_TransmitFile");	    errLen = PORT_Strlen(errString);	    if (errLen > sizeof msgBuf - 1) 	    	errLen = sizeof msgBuf - 1;	    PORT_Memcpy(msgBuf, errString, errLen);	    msgBuf[errLen] = 0;	    iovs[numIOVs].iov_base = msgBuf;	    iovs[numIOVs].iov_len  = PORT_Strlen(msgBuf);	    numIOVs++;	} else if (reqLen <= 0) {	/* hit eof */	    PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",			 bufDat);	    iovs[numIOVs].iov_base = msgBuf;	    iovs[numIOVs].iov_len  = PORT_Strlen(msgBuf);	    numIOVs++;	} else if (reqLen < bufDat) {	    PORT_Sprintf(msgBuf, "Discarded %d characters.\r\n", 	                 bufDat - reqLen);	    iovs[numIOVs].iov_base = msgBuf;	    iovs[numIOVs].iov_len  = PORT_Strlen(msgBuf);	    numIOVs++;	}	if (reqLen > 0) {	    if (verbose > 1) 	    	fwrite(buf, 1, reqLen, stdout);	/* display it */	    iovs[numIOVs].iov_base = buf;	    iovs[numIOVs].iov_len  = reqLen;	    numIOVs++;/*	    printSecurityInfo(ssl_sock); */	}	iovs[numIOVs].iov_base = (char *)EOFmsg;	iovs[numIOVs].iov_len  = sizeof EOFmsg - 1;	numIOVs++;	rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);	if (rv < 0) {	    errWarn("PR_Writev");	    break;	}    } while (0);cleanup:    if (ssl_sock) {        PR_Close(ssl_sock);    }    if (local_file_fd)	PR_Close(local_file_fd);    VLOG(("selfserv: handle_connection: exiting\n"));    /* do a nice shutdown if asked. */    if (!strncmp(buf, stopCmd, sizeof stopCmd - 1)) {	stopping = 1;        VLOG(("selfserv: handle_connection: stop command"));	PR_Interrupt(acceptorThread);        PZ_TraceFlush();    }    VLOG(("selfserv: handle_connection: exiting"));    return SECSuccess;	/* success */}