PR_Interrupt(acceptorThread);
handle_connection(     PRFileDesc *tcp_sock,    PRFileDesc *model_sock,    int         requestCert    ){    PRFileDesc *       ssl_sock = 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                i;    int                rv;    PRSocketOptionData opt;    char               msgBuf[120];    char               buf[10240];    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;    }    while (1) {	newln = 0;	i     = 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 (i < bufDat && newln < 2) {	    int octet = buf[i++];	    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 (i < bufDat && newln < 3) {	    int octet = buf[i++];	    if (octet == '\n') {		newln++;	    }	}	if (newln == 3)	    break;    }    bufDat = pBuf - buf;    if (bufDat) do {	/* just close if no data */	/* Have either (a) a complete get, (b) a complete post, (c) EOF */	if (i > 0 && !strncmp(buf, stopCmd, 4)) {	    PRFileDesc *local_file_fd = NULL;	    PRInt32     bytes;	    char *      pSave;	    PRFileInfo  info;	    char        saveChar;	    /* try to open the file named.  	     * If succesful, then write it to the client.	     */	    pSave = strpbrk(buf + 4, " \r\n");	    if (pSave) {		saveChar = *pSave;		*pSave = 0;	    }	    status = PR_GetFileInfo(buf + 4, &info);	    if (status == PR_SUCCESS &&		info.type == PR_FILE_FILE &&		info.size >= 0 &&		NULL != (local_file_fd = PR_Open(buf + 4, PR_RDONLY, 0))) {		bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,					sizeof outHeader - 1, 					PR_TRANSMITFILE_KEEP_OPEN,					PR_INTERVAL_NO_TIMEOUT);		if (bytes < 0) {		    errString = errWarn("PR_TransmitFile");		    i = PORT_Strlen(errString);		    PORT_Memcpy(buf, errString, i);		    goto send_answer;		} else {		    bytes -= sizeof outHeader - 1;		    FPRINTF(stderr, 			    "selfserv: PR_TransmitFile wrote %d bytes from %s\n",			    bytes, buf + 4);		}		PR_Close(local_file_fd);		break;	    }	    /* file didn't open. */	    if (pSave) {		*pSave = saveChar;	/* put it back. */	    }	}send_answer:	/* 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;		}	    }	}	rv = PR_Write(ssl_sock, outHeader, (sizeof(outHeader)) - 1);	if (rv < 0) {	    errWarn("PR_Write");	    break;	}	if (i <= 0) {	/* hit eof */	    PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",			 bufDat);	    rv = PR_Write(ssl_sock, msgBuf, PORT_Strlen(msgBuf));	    if (rv < 0) {		errWarn("PR_Write");		break;	    }	} else {	    if (verbose > 1) fwrite(buf, 1, i, stdout);	/* display it */	    rv = PR_Write(ssl_sock, buf, i);	    if (rv < 0) {		errWarn("PR_Write");		break;	    }	    printSecurityInfo(ssl_sock);	    if (i < bufDat) {		PORT_Sprintf(buf, "Discarded %d characters.\r\n", rv - i);		rv = PR_Write(ssl_sock, buf, PORT_Strlen(buf));		if (rv < 0) {		    errWarn("PR_Write");		    break;		}	    }	}	rv = PR_Write(ssl_sock, "EOF\r\n\r\n\r\n", 9);	if (rv < 0) {	    errWarn("PR_Write");	    break;	}    } while (0);cleanup:    PR_Close(ssl_sock);    VLOG(("selfserv: handle_connection: exiting\n"));    /* do a nice shutdown if asked. */    if (!strncmp(buf, stopCmd, strlen(stopCmd))) {	stopping = 1;        VLOG(("selfserv: handle_connection: stop command"));        PZ_TraceFlush();    }    VLOG(("selfserv: handle_connection: exiting"));    return SECSuccess;	/* success */}