Esempio n. 1
0
static void PR_CALLBACK Client(void *arg)
{
    PRStatus rv;
    PRUint8 buffer[100];
    PRIntn empty_flags = 0;
    PRIntn bytes_read, bytes_sent;
    PRFileDesc *stack = (PRFileDesc*)arg;

    /* Initialize the buffer so that Purify won't complain */
    memset(buffer, 0, sizeof(buffer));

    rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
    PR_ASSERT(PR_SUCCESS == rv);
    while (minor_iterations-- > 0)
    {
        bytes_sent = PR_Send(
            stack, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
        PR_ASSERT(sizeof(buffer) == bytes_sent);
        if (verbosity > chatty)
            PR_fprintf(logFile, "Client sending %d bytes\n", bytes_sent);
        bytes_read = PR_Recv(
            stack, buffer, bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT);
        if (verbosity > chatty)
            PR_fprintf(logFile, "Client receiving %d bytes\n", bytes_read);
        PR_ASSERT(bytes_read == bytes_sent);
    }

    if (verbosity > quiet)
        PR_fprintf(logFile, "Client shutting down stack\n");
    
    rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
}  /* Client */
Esempio n. 2
0
File: nss.c Progetto: 0w/moai-dev
/* return number of sent (non-SSL) bytes */
int Curl_nss_send(struct connectdata *conn,  /* connection data */
                  int sockindex,             /* socketindex */
                  const void *mem,           /* send this data */
                  size_t len)                /* amount to write */
{
  PRInt32 err;
  struct SessionHandle *data = conn->data;
  PRInt32 timeout;
  int rc;

  if(data->set.timeout)
    timeout = PR_MillisecondsToInterval((PRUint32)data->set.timeout);
  else
    timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);

  rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, timeout);

  if(rc < 0) {
    err = PR_GetError();

    if(err == PR_IO_TIMEOUT_ERROR) {
      failf(data, "SSL connection timeout");
      return CURLE_OPERATION_TIMEDOUT;
    }

    failf(conn->data, "SSL write: error %d", err);
    return -1;
  }
  return rc; /* number of bytes */
}
PR_END_EXTERN_C


/* ----------------------- filter method emulation ------------------------ */

static PRInt32 XP_EmulateWritev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
{
    PRInt32 nsent = 0;
    int i;

    for (i = 0; i < iov_size; i++) {
        PRInt32 rv;

        rv = PR_Send(fd, iov[i].iov_base, iov[i].iov_len, 0, timeout);
        if (rv == PR_FAILURE) {
            return PR_FAILURE;
        } else if (rv != iov[i].iov_len) {
            return nsent + rv;
        }

        nsent += rv;
    }

    return nsent;
}
Esempio n. 4
0
TransportResult TransportLayerDtls::SendPacket(const unsigned char *data,
                                               size_t len) {
  CheckThread();
  if (state_ != TS_OPEN) {
    MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Can't call SendPacket() in state "
              << state_);
    return TE_ERROR;
  }

  int32_t rv = PR_Send(ssl_fd_, data, len, 0, PR_INTERVAL_NO_WAIT);

  if (rv > 0) {
    // We have data
    MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << rv << " bytes to SSL Layer");
    return rv;
  }

  if (rv == 0) {
    TL_SET_STATE(TS_CLOSED);
    return 0;
  }

  int32_t err = PR_GetError();

  if (err == PR_WOULD_BLOCK_ERROR) {
    // This gets ignored
    MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Send would have blocked");
    return TE_WOULDBLOCK;
  }

  MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "NSS Error " << err);
  TL_SET_STATE(TS_ERROR);
  return TE_ERROR;
}
Esempio n. 5
0
static ssize_t nss_send(struct connectdata *conn,  /* connection data */
                        int sockindex,             /* socketindex */
                        const void *mem,           /* send this data */
                        size_t len,                /* amount to write */
                        CURLcode *curlcode)
{
  int rc;

  rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1);

  if(rc < 0) {
    PRInt32 err = PR_GetError();
    if(err == PR_WOULD_BLOCK_ERROR)
      *curlcode = CURLE_AGAIN;
    else {
      /* print the error number and error string */
      const char *err_name = nss_error_to_name(err);
      infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);

      /* print a human-readable message describing the error if available */
      nss_print_error_message(conn->data, err);

      *curlcode = (is_cc_error(err))
        ? CURLE_SSL_CERTPROBLEM
        : CURLE_SEND_ERROR;
    }
    return -1;
  }
  return rc; /* number of bytes */
}
Esempio n. 6
0
static void ConnectingThread(void *arg)
{
    PRInt32 nbytes;
#ifdef SYMBIAN
    char buf[256];
#else
    char buf[1024];
#endif
    PRFileDesc *sock;
    PRNetAddr peer_addr, *addr;

    addr = (PRNetAddr*)arg;

    sock = PR_NewTCPSocket();
    if (sock == NULL)
    {
        PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
        PR_ProcessExit(1);
    }

    if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_Connect (client) failed");
        PR_ProcessExit(1);
    }
    if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
        PR_ProcessExit(1);
    }

    /*
    ** Then wait between the connection coming up and sending the expected
    ** data. At some point in time, the server should fail due to a timeou
    ** on the AcceptRead() operation, which according to the document is
    ** only due to the read() portion.
    */
    PR_Sleep(write_dally);

    nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
    if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");

    nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
    if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
    else
    {
        PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
        buf[sizeof(buf) - 1] = '\0';
        PR_fprintf(std_out, "%s\n", buf);
    }

    if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
        PL_FPrintError(err_out, "PR_Shutdown (client) failed");

    if (PR_FAILURE == PR_Close(sock))
        PL_FPrintError(err_out, "PR_Close (client) failed");

    return;
}  /* ConnectingThread */
NSAPI_PUBLIC int net_write(SYS_NETFD fd, const void *buf, int sz)
{
    int rv;

    rv = PR_Send(fd, buf, sz, 0, PR_INTERVAL_NO_TIMEOUT);
    if(rv < 0) {
#ifdef XP_WIN32
        INTnet_cancelIO(fd);
#endif
        return IO_ERROR;
    }
    return rv;
}
Esempio n. 8
0
static void PR_CALLBACK Servette(void *arg)
{
    PRInt32 bytes, sampled;
    PRIntervalTime now, interval;
    PRBool do_display = PR_FALSE;
    PRFileDesc *client = (PRFileDesc*)arg;
    char *buffer = (char*)PR_Malloc(buffer_size);
    PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL);

    if (xport_buffer != -1)
    {
        PRStatus rv;
        PRSocketOptionData data;
        data.option = PR_SockOpt_RecvBufferSize;
        data.value.recv_buffer_size = (PRSize)xport_buffer;
        rv = PR_SetSocketOption(client, &data);
        if (PR_FAILURE == rv)
            PL_FPrintError(err, "PR_SetSocketOption - ignored");
        data.option = PR_SockOpt_SendBufferSize;
        data.value.send_buffer_size = (PRSize)xport_buffer;
        rv = PR_SetSocketOption(client, &data);
        if (PR_FAILURE == rv)
            PL_FPrintError(err, "PR_SetSocketOption - ignored");
    }

    do
    {
        bytes = PR_Send(
            client, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT);

        PR_Lock(shared->ml);
        now = PR_IntervalNow();
        shared->sampled += bytes;
        interval = now - shared->timein;
        if (interval > sampling_interval)
        {
            sampled = shared->sampled;
            shared->timein = now;
            shared->sampled = 0;
            do_display = PR_TRUE;
        }
        PR_Unlock(shared->ml);

        if (do_display)
        {
            PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval);
            PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate);
            do_display = PR_FALSE;
        }
    } while (bytes > 0);
}  /* Servette */
Esempio n. 9
0
File: nss.c Progetto: 499940913/moon
/* return number of sent (non-SSL) bytes */
int Curl_nss_send(struct connectdata *conn,  /* connection data */
                  int sockindex,             /* socketindex */
                  const void *mem,           /* send this data */
                  size_t len)                /* amount to write */
{
  int rc;

  rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1);

  if(rc < 0) {
    failf(conn->data, "SSL write: error %d", PR_GetError());
    return -1;
  }
  return rc; /* number of bytes */
}
Esempio n. 10
0
static void
serve_client_write(void *arg)
{
	Session *sp = (Session *) arg;
    int bytes;
	PRFileDesc *sockfd;
	char *buf;
	PRJob *jobp;

	sockfd = sp->iod.socket;
	buf = sp->in_buf->data;

    PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection);

	bytes = PR_Send(sockfd, buf, sp->bytes, 0, PR_INTERVAL_NO_TIMEOUT);
	PR_ASSERT(bytes == sp->bytes);

	if (bytes < 0) {
		return;
	}
	DPRINTF(("serve_client: write complete, msg(%d) \n", sp->msg_num));
    sp->msg_num++;
    if (sp->msg_num < num_tcp_mesgs_per_connection) {
		sp->bytes_read = 0;
		sp->iod.timeout = PR_SecondsToInterval(60);
		jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
							PR_FALSE);
		PR_ASSERT(NULL != jobp);
		return;
	}

	DPRINTF(("serve_client: read/write complete, msg(%d) \n", sp->msg_num));
    if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
        fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name);
    }

    PR_Close(sockfd);
    PR_EnterMonitor(sp->exit_mon);
    --(*sp->job_counterp);
    PR_Notify(sp->exit_mon);
    PR_ExitMonitor(sp->exit_mon);

    PR_DELETE(sp->in_buf);
    PR_DELETE(sp);

    return;
}
Esempio n. 11
0
/*
 * writen
 *    write data from buf to sockfd
 */
static PRInt32
writen(PRFileDesc *sockfd, char *buf, int len)
{
    int rem;
    int bytes;
    int offset = 0;

    for (rem=len; rem; offset += bytes, rem -= bytes) {
        DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
            PR_GetCurrentThread(), rem));
        bytes = PR_Send(sockfd, buf + offset, rem, 0,
            PR_INTERVAL_NO_TIMEOUT);
        DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
            PR_GetCurrentThread(), bytes));
        if (bytes <= 0)
            return -1;
    }
    return len;
}
Esempio n. 12
0
nsresult
SendAll(PRFileDesc *aSocket, const char *aData, size_t aDataLen)
{
  if (gDebugLevel >= DEBUG_VERBOSE) {
    fprintf(stderr, "sending '%s'\n", aData);
  }

  while (aDataLen > 0) {
    int32_t bytesSent = PR_Send(aSocket, aData, aDataLen, 0,
                                PR_INTERVAL_NO_TIMEOUT);
    if (bytesSent == -1) {
      PrintPRError("PR_Send failed");
      return NS_ERROR_FAILURE;
    }

    aDataLen -= bytesSent;
    aData += bytesSent;
  }

  return NS_OK;
}
Esempio n. 13
0
static void PR_CALLBACK Server(void *arg)
{
    PRStatus rv;
    PRUint8 buffer[100];
    PRFileDesc *service;
    PRUintn empty_flags = 0;
    PRIntn bytes_read, bytes_sent;
    PRFileDesc *stack = (PRFileDesc*)arg;
    PRNetAddr client_address;

    service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
    if (verbosity > quiet)
        PR_fprintf(logFile, "Server accepting connection\n");

    do
    {
        bytes_read = PR_Recv(
            service, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
        if (0 != bytes_read)
        {
            if (verbosity > chatty)
                PR_fprintf(logFile, "Server receiving %d bytes\n", bytes_read);
            PR_ASSERT(bytes_read > 0);
            bytes_sent = PR_Send(
                service, buffer, bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT);
            if (verbosity > chatty)
                PR_fprintf(logFile, "Server sending %d bytes\n", bytes_sent);
            PR_ASSERT(bytes_read == bytes_sent);
        }

    } while (0 != bytes_read);

    if (verbosity > quiet)
        PR_fprintf(logFile, "Server shutting down and closing stack\n");
    rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
    rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);

}  /* Server */
Esempio n. 14
0
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
        struct tls_connection *conn,
        const struct wpabuf *in_data) {
    PRInt32 res;
    struct wpabuf *buf;

    wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
            (int) wpabuf_len(in_data));
    res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
            0);
    if (res < 0) {
        wpa_printf(MSG_ERROR, "NSS: Encryption failed");
        return NULL;
    }
    if (conn->push_buf == NULL)
        return NULL;
    buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
    if (buf == NULL)
        os_free(conn->push_buf);
    conn->push_buf = NULL;
    conn->push_buf_len = 0;
    return buf;
}
Esempio n. 15
0
static ssize_t nss_send(struct connectdata *conn,  /* connection data */
                        int sockindex,             /* socketindex */
                        const void *mem,           /* send this data */
                        size_t len,                /* amount to write */
                        CURLcode *curlcode)
{
  int rc;

  rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1);

  if(rc < 0) {
    PRInt32 err = PR_GetError();
    if(err == PR_WOULD_BLOCK_ERROR)
      *curlcode = CURLE_AGAIN;
    else if(handle_cc_error(err, conn->data))
      *curlcode = CURLE_SSL_CERTPROBLEM;
    else {
      failf(conn->data, "SSL write: error %d", err);
      *curlcode = CURLE_SEND_ERROR;
    }
    return -1;
  }
  return rc; /* number of bytes */
}
Esempio n. 16
0
PRInt32 _PR_EmulateTransmitFile(PRFileDesc *sd, PRFileDesc *fd, 
const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
PRIntervalTime timeout)
{
	PRInt32 rv, count = 0;
	PRInt32 rlen;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	char *buf = NULL;
#define _TRANSMITFILE_BUFSIZE	(16 * 1024)

	if (_PR_PENDING_INTERRUPT(me)) {
		me->flags &= ~_PR_INTERRUPT;
		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
		return -1;
	}

	buf = PR_MALLOC(_TRANSMITFILE_BUFSIZE);
	if (buf == NULL) {
		PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
		return -1;
	}

	/*
	 * send headers, first
	 */
	while (hlen) {
		rv =  PR_Send(sd, headers, hlen, 0, timeout);
		if (rv < 0) {
			/* PR_Send() has invoked PR_SetError(). */
			rv = -1;
			goto done;
		} else {
			count += rv;
			headers = (const void*) ((const char*)headers + rv);
			hlen -= rv;
		}
	}
	/*
	 * send file, next
	 */
	while ((rlen = PR_Read(fd, buf, _TRANSMITFILE_BUFSIZE)) > 0) {
		while (rlen) {
			char *bufptr = buf;

			rv =  PR_Send(sd, bufptr, rlen,0,PR_INTERVAL_NO_TIMEOUT);
			if (rv < 0) {
				/* PR_Send() has invoked PR_SetError(). */
				rv = -1;
				goto done;
			} else {
				count += rv;
				bufptr = ((char*)bufptr + rv);
				rlen -= rv;
			}
		}
	}
	if (rlen == 0) {
		/*
		 * end-of-file
		 */
		if (flags & PR_TRANSMITFILE_CLOSE_SOCKET)
			PR_Close(sd);
		rv = count;
	} else {
		PR_ASSERT(rlen < 0);
		/* PR_Read() has invoked PR_SetError(). */
		rv = -1;
	}

done:
	if (buf)
		PR_DELETE(buf);
	return rv;
}
Esempio n. 17
0
static void _udp_event_cb(UDTSOCKET u, void* parm, int events){
    uint32_t data = 0;
    PRUdtSocketDesc* desc = (PRUdtSocketDesc*)parm;
    PR_AtomicIncrement(&desc->sign_cnt);
    PR_Send(desc->sock_pair1, (const char*)&data, sizeof(data), 0, 0);
}
Esempio n. 18
0
/*
 * UDP_Client
 *    Client Thread
 *    Create a socket and bind an address 
 *    Communicate with the server at the address specified in the argument.
 *    Fill in a buffer, write data to server, read it back and check
 *    for data corruption.
 *    Close the socket
 */
static void PR_CALLBACK
UDP_Client(void *arg)
{
    Client_Param *cp = (Client_Param *) arg;
    PRFileDesc *sockfd;
    buffer *in_buf, *out_buf;
    union PRNetAddr netaddr;
    PRInt32 bytes, i, rv;


    bytes = cp->datalen;
    out_buf = PR_NEW(buffer);
    if (out_buf == NULL) {
        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
        failed_already=1;
        return;
    }
    in_buf = PR_NEW(buffer);
    if (in_buf == NULL) {
        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
        failed_already=1;
        return;
    }
    if ((sockfd = PR_NewUDPSocket()) == NULL) {
        fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n");
        failed_already=1;
        return;
    }

    /*
     * bind an address for the client, let the system chose the port
     * number
     */
    memset(&netaddr, 0 , sizeof(netaddr));
    netaddr.inet.family = AF_INET;
    netaddr.inet.ip = PR_htonl(INADDR_ANY);
    netaddr.inet.port = PR_htons(0);
    if (PR_Bind(sockfd, &netaddr) < 0) {
        fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
        perror("PR_Bind");
        return;
    }

    if (PR_GetSockName(sockfd, &netaddr) < 0) {
        fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
        failed_already=1;
        return;
    }

    DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
        netaddr.inet.ip, netaddr.inet.port));

    netaddr.inet.family = cp->server_addr.inet.family;
    netaddr.inet.port = cp->server_addr.inet.port;
    netaddr.inet.ip = cp->server_addr.inet.ip;

    if (cp->udp_connect) {
        if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
            fprintf(stderr,"prsocket_test: PR_Connect failed\n");
            failed_already=1;
            return;
        }
    }

    for (i = 0; i < num_udp_datagrams_per_client; i++) {
        /*
         * fill in random data
         */
        DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n",
            PR_GetCurrentThread(), out_buf->data, bytes));
        memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes);
        /*
         * write to server
         */
        if (cp->udp_connect)
            rv = PR_Send(sockfd, out_buf->data, bytes, 0,
                PR_INTERVAL_NO_TIMEOUT);
        else
            rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr,
                PR_INTERVAL_NO_TIMEOUT);
        if (rv != bytes) {
            return;
        }
        DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
            PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
        if (cp->udp_connect)
            rv = PR_Recv(sockfd, in_buf->data, bytes, 0,
                PR_INTERVAL_NO_TIMEOUT);
        else
            rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
                PR_INTERVAL_NO_TIMEOUT);
        if (rv != bytes) {
            return;
        }
        DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n",
            PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data))));
        /*
         * verify the data read
         */
        if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
            fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n");
            failed_already=1;
            return;
        }
    }
    PR_Close(sockfd);

    PR_DELETE(in_buf);
    PR_DELETE(out_buf);

    /*
     * Decrement exit_counter and notify parent thread
     */

    PR_EnterMonitor(cp->exit_mon);
    --(*cp->exit_counter);
    PR_Notify(cp->exit_mon);
    PR_ExitMonitor(cp->exit_mon);
    PR_DELETE(cp);
    DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
}
Esempio n. 19
0
static void PR_CALLBACK Client(void *arg)
{
    PRStatus rv;
    PRIntn mits;
    PRInt32 ready;
    PRUint8 buffer[100];
    PRPollDesc polldesc;
    PRIntn empty_flags = 0;
    PRIntn bytes_read, bytes_sent;
    PRFileDesc *stack = (PRFileDesc*)arg;

    /* Initialize the buffer so that Purify won't complain */
    memset(buffer, 0, sizeof(buffer));

    rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
    if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError()))
    {
        if (verbosity > quiet)
            PR_fprintf(logFile, "Client connect 'in progress'\n");
        do
        {
            polldesc.fd = stack;
            polldesc.out_flags = 0;
            polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
            ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
            if ((1 != ready)  /* if not 1, then we're dead */
            || (0 == (polldesc.in_flags & polldesc.out_flags)))
                { PR_NOT_REACHED("Whoa!"); break; }
            if (verbosity > quiet)
                PR_fprintf(
                    logFile, "Client connect 'in progress' [0x%x]\n",
                    polldesc.out_flags);
            rv = PR_GetConnectStatus(&polldesc);
            if ((PR_FAILURE == rv)
            && (PR_IN_PROGRESS_ERROR != PR_GetError())) break;
        } while (PR_FAILURE == rv);
    }
    PR_ASSERT(PR_SUCCESS == rv);
    if (verbosity > chatty)
        PR_fprintf(logFile, "Client created connection\n");

    for (mits = 0; mits < minor_iterations; ++mits)
    {
        bytes_sent = 0;
        if (verbosity > quiet)
            PR_fprintf(logFile, "Client sending %d bytes\n", sizeof(buffer));
        do
        {
            if (verbosity > chatty)
                PR_fprintf(
                    logFile, "Client sending %d bytes\n",
                    sizeof(buffer) - bytes_sent);
            ready = PR_Send(
                stack, buffer + bytes_sent, sizeof(buffer) - bytes_sent,
                empty_flags, PR_INTERVAL_NO_TIMEOUT);
            if (verbosity > chatty)
                PR_fprintf(logFile, "Client send status [%d]\n", ready);
            if (0 < ready) bytes_sent += ready;
            else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
            {
                polldesc.fd = stack;
                polldesc.out_flags = 0;
                polldesc.in_flags = PR_POLL_WRITE;
                ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
                if ((1 != ready)  /* if not 1, then we're dead */
                || (0 == (polldesc.in_flags & polldesc.out_flags)))
                    { PR_NOT_REACHED("Whoa!"); break; }
            }
            else break;
        } while (bytes_sent < sizeof(buffer));
        PR_ASSERT(sizeof(buffer) == bytes_sent);

        bytes_read = 0;
        do
        {
            if (verbosity > chatty)
                PR_fprintf(
                    logFile, "Client receiving %d bytes\n",
                    bytes_sent - bytes_read);
            ready = PR_Recv(
                stack, buffer + bytes_read, bytes_sent - bytes_read,
                empty_flags, PR_INTERVAL_NO_TIMEOUT);
            if (verbosity > chatty)
                PR_fprintf(
                    logFile, "Client receive status [%d]\n", ready);
            if (0 < ready) bytes_read += ready;
            else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
            {
                polldesc.fd = stack;
                polldesc.out_flags = 0;
                polldesc.in_flags = PR_POLL_READ;
                ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
                if ((1 != ready)  /* if not 1, then we're dead */
                || (0 == (polldesc.in_flags & polldesc.out_flags)))
                    { PR_NOT_REACHED("Whoa!"); break; }
            }
            else break;
        } while (bytes_read < bytes_sent);
        if (verbosity > chatty)
            PR_fprintf(logFile, "Client received %d bytes\n", bytes_read);
        PR_ASSERT(bytes_read == bytes_sent);
    }

    if (verbosity > quiet)
        PR_fprintf(logFile, "Client shutting down stack\n");
    
    rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
}  /* Client */
/*
 * ar_send_res_msg
 *
 * When sending queries to nameservers listed in the resolv.conf file,
 * don't send a query to every one, but increase the number sent linearly
 * to match the number of resends. This increase only occurs if there are
 * multiple nameserver entries in the resolv.conf file.
 * The return value is the number of messages successfully sent to 
 * nameservers or -1 if no successful sends.
 */
int Resolver :: ar_send_res_msg(char *msg, int len, int rcount)
{
    int    i;
    int    sent = 0;

#ifdef HPUX
    /* VB: _res on HP is thread specific and needs to be initialized 
       on every thread */
    if (!(_res.options & RES_INIT)) {
        res_init();
    }
#endif
#ifdef Linux
    res_init_tls();
#endif

    if (!msg)
        return -1;

    if (_res.options & RES_PRIMARY)
        rcount = 1;
    rcount = (_res.nscount > rcount) ? rcount : _res.nscount;

    if (ar_vc)
    {
        ar_reinfo.re_sent++;
        sent++;
        if (PR_Send(afd, msg, len, 0, PR_INTERVAL_NO_TIMEOUT) == -1)
        {
            int errtmp = errno;
            PR_ASSERT(0);
            (void)PR_Close(afd);
            errno = errtmp;
            afd = NULL;
        }
    }
    else
        for (i = 0; i < rcount; i++)
        {
            struct sockaddr_in sin = _res.nsaddr_list[i];
            // XXX jpierre is this legal ???
            PRNetAddr *paddr = (PRNetAddr *)&sin;
#ifdef AIX
            PRNetAddr addr;
            /* For AIX struct sockaddr_in { uchar_t sin_len; 
             *                      sa_family_t sin_family;
             *                      in_port_t sin_port;
             * struct in_addr sin_addr; uchar_t sin_zero[8]; };
             * struct in_addr { in_addr_t s_addr; };
             * typedef uint32_t in_addr_t;
             *
             * In NSPR PRNetAddr is :
             *  union PRNetAddr { struct { PRUint16 family; 
             *                             char data[14]; } raw;
             *   struct { PRUint16 family; PRUint16 port; 
             *           PRUint32 ip; char pad[8]; } inet; ... }
             */
            PR_ASSERT(sin.sin_family == AF_INET);
            /* xxx strange when request is sent to IPV6 address 
             * then also address family is AF_INET 
             */
            memset(&addr, 0, sizeof(addr));
            addr.raw.family = sin.sin_family;
            addr.inet.family = sin.sin_family;
            addr.inet.port  = sin.sin_port;
            addr.inet.ip = sin.sin_addr.s_addr;
            memcpy(addr.inet.pad, sin.sin_zero, 8);
            paddr = &addr;
#endif
            if (PR_SendTo(afd, msg, len, 0,
                paddr,
                PR_INTERVAL_NO_TIMEOUT) == len) {
                ar_reinfo.re_sent++;
                sent++;
            }
            else
            {
                PR_ASSERT(0);
            }
        }
    return (sent) ? sent : -1;
}
void
WorkerThreadFunc(void *_listenSock)
{
    PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
    PRInt32 bytesRead;
    PRInt32 bytesWritten;
    char *dataBuf;
    char *sendBuf;

    if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
            _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
    dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
    if (!dataBuf)
        if (debug_mode) printf("\tServer could not malloc space!?\n");
    sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
    if (!sendBuf)
        if (debug_mode) printf("\tServer could not malloc space!?\n");

    if (debug_mode) DPRINTF("\tServer worker thread running\n");

    while(1) {
        PRInt32 bytesToRead = _client_data;
        PRInt32 bytesToWrite = _server_data;
        PRFileDesc *newSock;
        PRNetAddr *rAddr;
        PRInt32 loops = 0;

        loops++;

        if (debug_mode) DPRINTF("\tServer thread going into accept\n");

        bytesRead = PR_AcceptRead(listenSock, 
                                  &newSock,
                                  &rAddr,
                                  dataBuf,
                                  bytesToRead,
                                  PR_INTERVAL_NO_TIMEOUT);

        if (bytesRead < 0) {
            if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
            continue;
        }

        if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
        
        PR_AtomicIncrement(&workerThreadsBusy);
#ifdef SYMBIAN
        if (workerThreadsBusy == workerThreads && workerThreads<1) {
#else
        if (workerThreadsBusy == workerThreads) {
#endif
            PR_Lock(workerThreadsLock);
            if (workerThreadsBusy == workerThreads) {
                PRThread *WorkerThread;

                WorkerThread = PR_CreateThread(
                                  PR_SYSTEM_THREAD,
                                  WorkerThreadFunc,
                                  listenSock,
                                  PR_PRIORITY_NORMAL,
                                  ServerScope,
                                  PR_UNJOINABLE_THREAD,
                                  THREAD_STACKSIZE);

                if (!WorkerThread) {
                    if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
                } else {
                    PR_AtomicIncrement(&workerThreads);
                    if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
                }
            }
            PR_Unlock(workerThreadsLock);
        }
 
        bytesToRead -= bytesRead;
        while (bytesToRead) {
            bytesRead = PR_Recv(newSock, 
                                dataBuf, 
                                bytesToRead, 
                                0, 
                                PR_INTERVAL_NO_TIMEOUT);
            if (bytesRead < 0) {
                if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
                continue;
            }
            if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
        }

        bytesWritten = PR_Send(newSock,
                               sendBuf, 
                               bytesToWrite, 
                               0, 
                               PR_INTERVAL_NO_TIMEOUT);
        if (bytesWritten != _server_data) {
            if (debug_mode) printf("\tError sending data to client (%d, %d)\n", 
                bytesWritten, PR_GetOSError());
        } else {
            if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
        }

        PR_Close(newSock);
        PR_AtomicDecrement(&workerThreadsBusy);
    }
}

PRFileDesc *
ServerSetup(void)
{
    PRFileDesc *listenSocket;
    PRSocketOptionData sockOpt;
    PRNetAddr serverAddr;
    PRThread *WorkerThread;

    if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
        if (debug_mode) printf("\tServer error creating listen socket\n");
		else failed_already=1;
        return NULL;
    }

    sockOpt.option = PR_SockOpt_Reuseaddr;
    sockOpt.value.reuse_addr = PR_TRUE;
    if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
        if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
                PR_GetOSError());
		else failed_already=1;
        PR_Close(listenSocket);
        return NULL;
    }

    memset(&serverAddr, 0, sizeof(PRNetAddr));
    serverAddr.inet.family = PR_AF_INET;
    serverAddr.inet.port = PR_htons(PORT);
    serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);

    if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
        if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
                PR_GetOSError());
		else failed_already=1;
        PR_Close(listenSocket);
        return NULL;
    }

    if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
        if (debug_mode) printf("\tServer error listening to server socket\n");
		else failed_already=1;
        PR_Close(listenSocket);

        return NULL;
    }

    /* Create Clients */
    workerThreads = 0;
    workerThreadsBusy = 0;

    workerThreadsLock = PR_NewLock();

    WorkerThread = PR_CreateThread(
                      PR_SYSTEM_THREAD,
                      WorkerThreadFunc,
                      listenSocket,
                      PR_PRIORITY_NORMAL,
                      ServerScope,
                      PR_UNJOINABLE_THREAD,
                      THREAD_STACKSIZE);

    if (!WorkerThread) {
        if (debug_mode) printf("error creating working thread\n");
        PR_Close(listenSocket);
        return NULL;
    }
    PR_AtomicIncrement(&workerThreads);
    if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");

    return listenSocket;
}
static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
    PRStatus drv, rv;
    char buffer[1024];
    PRFileDesc *file = NULL;
    PRThread * me = PR_GetCurrentThread();
    PRInt32 bytes, descbytes, netbytes, filebytes = 0;
    CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
    PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT);

    TEST_LOG(
        cltsrv_log_file, TEST_LOG_VERBOSE,
        ("\tProcessRequest(0x%p): receiving desciptor\n", me));
    bytes = PR_Recv(
        fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout);
    if (-1 == bytes)
    {
        rv = PR_FAILURE;
        if (Aborted(rv)) goto exit;
        if (PR_IO_TIMEOUT_ERROR == PR_GetError())
        {
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_ERROR,
                ("\tProcessRequest(0x%p): receive timeout\n", me));
        }
        goto exit;
    }
    if (0 == bytes)
    {
        rv = PR_FAILURE;
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_ERROR,
            ("\tProcessRequest(0x%p): unexpected end of file\n", me));
        goto exit;
    }
    descbytes = PR_ntohl(descriptor->size);
    TEST_ASSERT(sizeof(*descriptor) == bytes);

    TEST_LOG(
        cltsrv_log_file, TEST_LOG_VERBOSE, 
        ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n",
        me, descbytes, descriptor->filename));

    file = PR_Open(
        descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666);
    if (NULL == file)
    {
        rv = PR_FAILURE;
        if (Aborted(rv)) goto aborted;
        if (PR_IO_TIMEOUT_ERROR == PR_GetError())
        {
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_ERROR,
                ("\tProcessRequest(0x%p): open file timeout\n", me));
            goto aborted;
        }
    }
    TEST_ASSERT(NULL != file);

    filebytes = 0;
    while (filebytes < descbytes)
    {
        netbytes = sizeof(buffer);
        if ((descbytes - filebytes) < netbytes)
            netbytes = descbytes - filebytes;
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_VERBOSE,
            ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes));
        bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
        if (-1 == bytes)
        {
            rv = PR_FAILURE;
            if (Aborted(rv)) goto aborted;
            if (PR_IO_TIMEOUT_ERROR == PR_GetError())
            {
                TEST_LOG(
                    cltsrv_log_file, TEST_LOG_ERROR,
                    ("\t\tProcessRequest(0x%p): receive data timeout\n", me));
                goto aborted;
            }
            /*
             * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED)
             * on NT here.  This is equivalent to ECONNRESET on Unix.
             *     -wtc
             */
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_WARNING,
                ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n",
                me, PR_GetError(), PR_GetOSError()));
            goto aborted;
        }
        if(0 == bytes)
        {
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_WARNING,
                ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me));
            rv = PR_FAILURE;
            goto aborted;
        }
        filebytes += bytes;
        netbytes = bytes;
        /* The byte count for PR_Write should be positive */
        MY_ASSERT(netbytes > 0);
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_VERBOSE,
            ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes));
        bytes = PR_Write(file, buffer, netbytes);
        if (netbytes != bytes)
        {
            rv = PR_FAILURE;
            if (Aborted(rv)) goto aborted;
            if (PR_IO_TIMEOUT_ERROR == PR_GetError())
            {
                TEST_LOG(
                    cltsrv_log_file, TEST_LOG_ERROR,
                    ("\t\tProcessRequest(0x%p): write file timeout\n", me));
                goto aborted;
            }
        }
        TEST_ASSERT(bytes > 0);
    }

    PR_Lock(server->ml);
    server->operations += 1;
    server->bytesTransferred += filebytes;
    PR_Unlock(server->ml);

    rv = PR_Close(file);
    if (Aborted(rv)) goto aborted;
    TEST_ASSERT(PR_SUCCESS == rv);
    file = NULL;

    TEST_LOG(
        cltsrv_log_file, TEST_LOG_VERBOSE,
        ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename));
    file = PR_Open(descriptor->filename, PR_RDONLY, 0);
    if (NULL == file)
    {
        rv = PR_FAILURE;
        if (Aborted(rv)) goto aborted;
        if (PR_IO_TIMEOUT_ERROR == PR_GetError())
        {
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_ERROR,
                ("\t\tProcessRequest(0x%p): open file timeout\n",
                PR_GetCurrentThread()));
            goto aborted;
        }
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_ERROR,
            ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n",
            me, PR_GetError(), PR_GetOSError()));
        goto aborted;
    }
    TEST_ASSERT(NULL != file);

    netbytes = 0;
    while (netbytes < descbytes)
    {
        filebytes = sizeof(buffer);
        if ((descbytes - netbytes) < filebytes)
            filebytes = descbytes - netbytes;
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_VERBOSE,
            ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes));
        bytes = PR_Read(file, buffer, filebytes);
        if (filebytes != bytes)
        {
            rv = PR_FAILURE;
            if (Aborted(rv)) goto aborted;
            if (PR_IO_TIMEOUT_ERROR == PR_GetError())
                TEST_LOG(
                    cltsrv_log_file, TEST_LOG_ERROR,
                    ("\t\tProcessRequest(0x%p): read file timeout\n", me));
            else
                TEST_LOG(
                    cltsrv_log_file, TEST_LOG_ERROR,
                    ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n",
                    me, PR_GetError(), PR_GetOSError()));
            goto aborted;
        }
        TEST_ASSERT(bytes > 0);
        netbytes += bytes;
        filebytes = bytes;
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_VERBOSE,
            ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes));
        bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
        if (filebytes != bytes)
        {
            rv = PR_FAILURE;
            if (Aborted(rv)) goto aborted;
            if (PR_IO_TIMEOUT_ERROR == PR_GetError())
            {
                TEST_LOG(
                    cltsrv_log_file, TEST_LOG_ERROR,
                    ("\t\tProcessRequest(0x%p): send data timeout\n", me));
                goto aborted;
            }
            break;
        }
       TEST_ASSERT(bytes > 0);
    }
    
    PR_Lock(server->ml);
    server->bytesTransferred += filebytes;
    PR_Unlock(server->ml);

    rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
    if (Aborted(rv)) goto aborted;

    rv = PR_Close(file);
    if (Aborted(rv)) goto aborted;
    TEST_ASSERT(PR_SUCCESS == rv);
    file = NULL;

aborted:
    PR_ClearInterrupt();
    if (NULL != file) PR_Close(file);
    drv = PR_Delete(descriptor->filename);
    TEST_ASSERT(PR_SUCCESS == drv);
exit:
    TEST_LOG(
        cltsrv_log_file, TEST_LOG_VERBOSE,
        ("\t\tProcessRequest(0x%p): Finished\n", me));

    PR_DELETE(descriptor);

#if defined(WIN95)
    PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */
#endif
    return rv;
}  /* ProcessRequest */
static void PR_CALLBACK Client(void *arg)
{
    PRStatus rv;
    PRIntn index;
    char buffer[1024];
    PRFileDesc *fd = NULL;
    PRUintn clipping = DEFAULT_CLIPPING;
    PRThread *me = PR_GetCurrentThread();
    CSClient_t *client = (CSClient_t*)arg;
    CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
    PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT);


    for (index = 0; index < sizeof(buffer); ++index)
        buffer[index] = (char)index;

    client->started = PR_IntervalNow();

    PR_Lock(client->ml);
    client->state = cs_run;
    PR_NotifyCondVar(client->stateChange);
    PR_Unlock(client->ml);

    TimeOfDayMessage("Client started at", me);

    while (cs_run == client->state)
    {
        PRInt32 bytes, descbytes, filebytes, netbytes;

        (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer));
        TEST_LOG(cltsrv_log_file, TEST_LOG_INFO, 
            ("\tClient(0x%p): connecting to server at %s\n", me, buffer));

        fd = PR_Socket(domain, SOCK_STREAM, protocol);
        TEST_ASSERT(NULL != fd);
        rv = PR_Connect(fd, &client->serverAddress, timeout);
        if (PR_FAILURE == rv)
        {
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_ERROR,
                ("\tClient(0x%p): conection failed (%d, %d)\n",
                me, PR_GetError(), PR_GetOSError()));
            goto aborted;
        }

        memset(descriptor, 0, sizeof(*descriptor));
        descriptor->size = PR_htonl(descbytes = rand() % clipping);
        PR_snprintf(
            descriptor->filename, sizeof(descriptor->filename),
            "CS%p%p-%p.dat", client->started, me, client->operations);
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_VERBOSE,
            ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes));
        bytes = PR_Send(
            fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout);
        if (sizeof(CSDescriptor_t) != bytes)
        {
            if (Aborted(PR_FAILURE)) goto aborted;
            if (PR_IO_TIMEOUT_ERROR == PR_GetError())
            {
                TEST_LOG(
                    cltsrv_log_file, TEST_LOG_ERROR,
                    ("\tClient(0x%p): send descriptor timeout\n", me));
                goto retry;
            }
        }
        TEST_ASSERT(sizeof(*descriptor) == bytes);

        netbytes = 0;
        while (netbytes < descbytes)
        {
            filebytes = sizeof(buffer);
            if ((descbytes - netbytes) < filebytes)
                filebytes = descbytes - netbytes;
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_VERBOSE,
                ("\tClient(0x%p): sending %d bytes\n", me, filebytes));
            bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
            if (filebytes != bytes)
            {
                if (Aborted(PR_FAILURE)) goto aborted;
                if (PR_IO_TIMEOUT_ERROR == PR_GetError())
                {
                    TEST_LOG(
                        cltsrv_log_file, TEST_LOG_ERROR,
                        ("\tClient(0x%p): send data timeout\n", me));
                    goto retry;
                }
            }
            TEST_ASSERT(bytes == filebytes);
            netbytes += bytes;
        }
        filebytes = 0;
        while (filebytes < descbytes)
        {
            netbytes = sizeof(buffer);
            if ((descbytes - filebytes) < netbytes)
                netbytes = descbytes - filebytes;
            TEST_LOG(
                cltsrv_log_file, TEST_LOG_VERBOSE,
                ("\tClient(0x%p): receiving %d bytes\n", me, netbytes));
            bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
            if (-1 == bytes)
            {
                if (Aborted(PR_FAILURE))
                {
                    TEST_LOG(
                        cltsrv_log_file, TEST_LOG_ERROR,
                        ("\tClient(0x%p): receive data aborted\n", me));
                    goto aborted;
                }
                else if (PR_IO_TIMEOUT_ERROR == PR_GetError())
                    TEST_LOG(
                        cltsrv_log_file, TEST_LOG_ERROR,
                        ("\tClient(0x%p): receive data timeout\n", me));
				else
                    TEST_LOG(
                        cltsrv_log_file, TEST_LOG_ERROR,
                        ("\tClient(0x%p): receive error (%d, %d)\n",
						me, PR_GetError(), PR_GetOSError()));
                goto retry;
           }
            if (0 == bytes)
            {
                TEST_LOG(
                    cltsrv_log_file, TEST_LOG_ERROR,
                    ("\t\tClient(0x%p): unexpected end of stream\n",
                    PR_GetCurrentThread()));
                break;
            }
            filebytes += bytes;
        }

        rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
        if (Aborted(rv)) goto aborted;
        TEST_ASSERT(PR_SUCCESS == rv);
retry:
        (void)PR_Close(fd); fd = NULL;
        TEST_LOG(
            cltsrv_log_file, TEST_LOG_INFO,
            ("\tClient(0x%p): disconnected from server\n", me));

        PR_Lock(client->ml);
        client->operations += 1;
        client->bytesTransferred += 2 * descbytes;
        rv = PR_WaitCondVar(client->stateChange, rand() % clipping);
        PR_Unlock(client->ml);
        if (Aborted(rv)) break;
    }

aborted:
    client->stopped = PR_IntervalNow();

    PR_ClearInterrupt();
    if (NULL != fd) rv = PR_Close(fd);

    PR_Lock(client->ml);
    client->state = cs_exit;
    PR_NotifyCondVar(client->stateChange);
    PR_Unlock(client->ml);
    PR_DELETE(descriptor);
    TEST_LOG(
        cltsrv_log_file, TEST_LOG_ALWAYS,
        ("\tClient(0x%p): stopped after %u operations and %u bytes\n",
        PR_GetCurrentThread(), client->operations, client->bytesTransferred));

}  /* Client */
Esempio n. 24
0
JNIEXPORT void JNICALL 
Java_org_mozilla_jss_ssl_SSLSocket_socketWrite(JNIEnv *env, jobject self, 
    jbyteArray bufBA, jint off, jint len, jint timeout)
{
    JSSL_SocketData *sock = NULL;
    jbyte *buf = NULL;
    jint size;
    PRIntervalTime ivtimeout;
    PRThread *me;
    PRInt32 numwrit;

    if( bufBA == NULL ) {
        JSS_throw(env, NULL_POINTER_EXCEPTION);
        goto finish;
    }

    size = (*env)->GetArrayLength(env, bufBA);
    if( off < 0 || len < 0 || (off+len) > size ) {
        JSS_throw(env, INDEX_OUT_OF_BOUNDS_EXCEPTION);
        goto finish;
    }

    buf = (*env)->GetByteArrayElements(env, bufBA, NULL);
    if( buf == NULL ) {
        goto finish;
    }

    ivtimeout = (timeout > 0) ? PR_MillisecondsToInterval(timeout)
                              : PR_INTERVAL_NO_TIMEOUT;

    /* get the socket */
    if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
        goto finish;
    }
    /* set the current thread doing the write */
    me = PR_GetCurrentThread();
    PR_Lock(sock->lock);
    if ( sock->closePending ) {
       PR_Unlock(sock->lock);
       JSSL_throwSSLSocketException(env, "Write operation interrupted");
       goto finish;
    }
    PR_ASSERT(sock->writer == NULL);
    sock->writer = me;
    PR_Unlock(sock->lock);

    numwrit = PR_Send(sock->fd, buf+off, len, 0 /*flags*/, ivtimeout);

    PR_Lock(sock->lock);
    PR_ASSERT(sock->writer == me);
    sock->writer = NULL;
    PR_Unlock(sock->lock);

    if( numwrit < 0 ) {
        PRErrorCode err = PR_GetError();
        if( err == PR_PENDING_INTERRUPT_ERROR ) {
#ifdef WINNT
            /* clean up after PR_Interrupt called by abortReadWrite. */
            PR_NT_CancelIo(sock->fd);
#endif 
            JSSL_throwSSLSocketException(env, "Write operation interrupted");
        } else if( err == PR_IO_TIMEOUT_ERROR ) {
#ifdef WINNT
            /*
             * if timeout was set, and the PR_Send() timed out,
             * then cancel the I/O on the socket, otherwise PR_Send()
             * will always return PR_IO_PENDING_ERROR on subsequent
             * calls
             */
            PR_NT_CancelIo(sock->fd);
#endif 
            JSSL_throwSSLSocketException(env, "Operation timed out");
        } else {
            JSSL_throwSSLSocketException(env, "Failed to write to socket");
        }
        goto finish;
    }
    /* PR_Send is supposed to block until it sends everything */
    PR_ASSERT(numwrit == len);

finish:
    if( buf != NULL ) {
        (*env)->ReleaseByteArrayElements(env, bufBA, buf, JNI_ABORT);
    }
    EXCEPTION_CHECK(env, sock)
}
/* Non-blocking I/O */
static void ClientNB(void *arg)
{
    PRFileDesc *sock;
    PRSocketOptionData opt;
    PRUint16 port = (PRUint16) arg;
    PRNetAddr addr;
    char buf[BUFFER_SIZE];
    PRPollDesc pd;
    PRInt32 npds;
    PRInt32 nbytes;
    int i;
    int j;

    sock = PR_OpenTCPSocket(PR_AF_INET6);
    if (NULL == sock) {
        fprintf(stderr, "PR_OpenTCPSocket failed\n");
        exit(1);
    }
    opt.option = PR_SockOpt_Nonblocking;
    opt.value.non_blocking = PR_TRUE;
    if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) {
        fprintf(stderr, "PR_SetSocketOption failed\n");
        exit(1);
    }
    memset(&addr, 0, sizeof(addr));
    if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr)
            == PR_FAILURE) {
        fprintf(stderr, "PR_SetNetAddr failed\n");
        exit(1);
    }
    if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
        if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
            fprintf(stderr, "PR_Connect failed\n");
            exit(1);
        }
        pd.fd = sock;
        pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
        npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == npds) {
            fprintf(stderr, "PR_Poll failed\n");
            exit(1);
        }
        if (1 != npds) {
            fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
            exit(1);
        }
        if (PR_GetConnectStatus(&pd) == PR_FAILURE) {
            fprintf(stderr, "PR_GetConnectStatus failed\n");
            exit(1);
        }
    }

    for (i = 0; i < iterations; i++) {
        PR_Sleep(PR_SecondsToInterval(1));
        memset(buf, 2*i, send_amount[i]);
        while ((nbytes = PR_Send(sock, buf, send_amount[i],
                0, PR_INTERVAL_NO_TIMEOUT)) == -1) {
            if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
                fprintf(stderr, "PR_Send failed\n");
                exit(1);
            }
            pd.fd = sock;
            pd.in_flags = PR_POLL_WRITE;
            npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
            if (-1 == npds) {
                fprintf(stderr, "PR_Poll failed\n");
                exit(1);
            }
            if (1 != npds) {
                fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
                exit(1);
            }
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
            exit(1);
        }

        memset(buf, 0, sizeof(buf));
        while ((nbytes = PR_Recv(sock, buf, recv_amount[i],
                PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) {
            if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
                fprintf(stderr, "PR_Recv failed\n");
                exit(1);
            }
            pd.fd = sock;
            pd.in_flags = PR_POLL_READ;
            npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
            if (-1 == npds) {
                fprintf(stderr, "PR_Poll failed\n");
                exit(1);
            }
            if (1 != npds) {
                fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
                exit(1);
            }
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i+1) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i+1, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "client: peeked expected data\n");

        memset(buf, 0, sizeof(buf));
        nbytes = PR_Recv(sock, buf, recv_amount[i],
                PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Recv failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i+1) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i+1, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "client: peeked expected data\n");

        memset(buf, 0, sizeof(buf));
        nbytes = PR_Recv(sock, buf, recv_amount[i],
                0, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Recv failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i+1) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i+1, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "client: received expected data\n");
    }
    if (PR_Close(sock) == PR_FAILURE) {
        fprintf(stderr, "PR_Close failed\n");
        exit(1);
    }
}
Esempio n. 26
0
static void PR_CALLBACK
ClientThread(void *_action)
{
    PRInt32 action = * (PRInt32 *) _action;
    PRInt32 iterations = count;
    PRFileDesc *sock = NULL;

    serverAddr.inet.family = AF_INET;
    serverAddr.inet.port = PR_htons(BASE_PORT);
    serverAddr.inet.ip = PR_htonl(INADDR_LOOPBACK);

    for (; iterations--;) {
        PRInt32 rv;
        char buf[CLIENT_DATA];

        sock = PR_NewTCPSocket();
        if (!sock) {
            if (!debug_mode)
                failed_already=1;
            else    
                printf("client: unable to create socket\n");
            return;
        }

        if (action != CLIENT_TIMEOUT_ACCEPT) {

            if ((rv = PR_Connect(sock, &serverAddr,
                timeoutTime)) < 0) {
                if (!debug_mode)
                    failed_already=1;
                else    
                    printf(
                        "client: unable to connect to server (%ld, %ld, %ld, %ld)\n",
                        iterations, rv, PR_GetError(),
                        PR_GetOSError());
                goto ErrorExit;
            }

            if (action != CLIENT_TIMEOUT_SEND) {
                if ((rv = PR_Send(sock, buf, CLIENT_DATA,
                    0, timeoutTime))< 0) {
                    if (!debug_mode)
                        failed_already=1;
                    else    
                        printf("client: unable to send to server (%d, %ld, %ld)\n",
                            CLIENT_DATA, rv,
                            PR_GetError());
                	goto ErrorExit;
                }
            } else {
                PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS+
                    1));
            }
        } else {
            PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS+
                1));
        }
        if (debug_mode)
            printf(".");
        PR_Close(sock);
    }
    if (debug_mode)
        printf("\n");

ErrorExit:
	if (sock != NULL)
        PR_Close(sock);
}
void
ClientThreadFunc(void *unused)
{
    PRNetAddr serverAddr;
    PRFileDesc *clientSocket;
    char *sendBuf;
    char *recvBuf;
    PRInt32 rv;
    PRInt32 bytesNeeded;

    sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
    if (!sendBuf)
        if (debug_mode) printf("\tClient could not malloc space!?\n");
    recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
    if (!recvBuf)
        if (debug_mode) printf("\tClient could not malloc space!?\n");

    memset(&serverAddr, 0, sizeof(PRNetAddr));
    serverAddr.inet.family = PR_AF_INET;
    serverAddr.inet.port = PR_htons(PORT);
    serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);

    while(numRequests > 0) {

        if ( (numRequests % 10) == 0 )
            if (debug_mode) printf(".");
        if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);

        clientSocket = PR_NewTCPSocket();
        if (!clientSocket) {
            if (debug_mode) printf("Client error creating socket: OS error %d\n",
		    PR_GetOSError());
            continue;
        }

        if (debug_mode) DPRINTF("\tClient connecting\n");

        rv = PR_Connect(clientSocket, 
                        &serverAddr,
                        PR_INTERVAL_NO_TIMEOUT);
        if (!clientSocket) {
            if (debug_mode) printf("\tClient error connecting\n");
            continue;
        }

        if (debug_mode) DPRINTF("\tClient connected\n");

        rv = PR_Send(clientSocket, 
                     sendBuf, 
                     _client_data, 
                     0, 
                     PR_INTERVAL_NO_TIMEOUT);
        if (rv != _client_data) {
            if (debug_mode) printf("Client error sending data (%d)\n", rv);
            PR_Close(clientSocket);
            continue;
        }

        if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);

        bytesNeeded = _server_data;
        while(bytesNeeded) {
            rv = PR_Recv(clientSocket, 
                         recvBuf, 
                         bytesNeeded, 
                         0, 
                         PR_INTERVAL_NO_TIMEOUT);
            if (rv <= 0) {
                if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", 
                    rv, (_server_data - bytesNeeded), _server_data);
                break;
            }
            if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
            bytesNeeded -= rv;
        }

        PR_Close(clientSocket);
 
        PR_AtomicDecrement(&numRequests);
    }

    PR_EnterMonitor(clientMonitor);
    --numClients;
    PR_Notify(clientMonitor);
    PR_ExitMonitor(clientMonitor);

    PR_DELETE(sendBuf);
    PR_DELETE(recvBuf);
}
Esempio n. 28
0
void
WorkerThreadFunc(void *_listenSock)
{
    PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
    PRInt32 bytesRead;
    PRInt32 bytesWritten;
    char *dataBuf;
    char *sendBuf;

    if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
            _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
    dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
    if (!dataBuf)
        if (debug_mode) printf("\tServer could not malloc space!?\n");
    sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
    if (!sendBuf)
        if (debug_mode) printf("\tServer could not malloc space!?\n");

    if (debug_mode) DPRINTF("\tServer worker thread running\n");

    while(1) {
        PRInt32 bytesToRead = _client_data;
        PRInt32 bytesToWrite = _server_data;
        PRFileDesc *newSock;
        PRNetAddr *rAddr;
        PRInt32 loops = 0;

        loops++;

        if (debug_mode) DPRINTF("\tServer thread going into accept\n");

        bytesRead = PR_AcceptRead(listenSock, 
                                  &newSock,
                                  &rAddr,
                                  dataBuf,
                                  bytesToRead,
                                  PR_INTERVAL_NO_TIMEOUT);

        if (bytesRead < 0) {
            if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
            continue;
        }

        if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
        
        PR_AtomicIncrement(&workerThreadsBusy);
        if (workerThreadsBusy == workerThreads) {

            PR_Lock(workerThreadsLock);
            if (workerThreadsBusy == workerThreads) {
                PRThread *WorkerThread;

                WorkerThread = PR_CreateThread(
                                  PR_SYSTEM_THREAD,
                                  WorkerThreadFunc,
                                  listenSock,
                                  PR_PRIORITY_NORMAL,
                                  ServerScope,
                                  PR_UNJOINABLE_THREAD,
                                  THREAD_STACKSIZE);

                if (!WorkerThread) {
                    if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
                } else {
                    PR_AtomicIncrement(&workerThreads);
                    if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
                }
            }
            PR_Unlock(workerThreadsLock);
        }
 
        bytesToRead -= bytesRead;
        while (bytesToRead) {
            bytesRead = PR_Recv(newSock, 
                                dataBuf, 
                                bytesToRead, 
                                0, 
                                PR_INTERVAL_NO_TIMEOUT);
            if (bytesRead < 0) {
                if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
                continue;
            }
            if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
        }

        bytesWritten = PR_Send(newSock,
                               sendBuf, 
                               bytesToWrite, 
                               0, 
                               PR_INTERVAL_NO_TIMEOUT);
        if (bytesWritten != _server_data) {
            if (debug_mode) printf("\tError sending data to client (%d, %d)\n", 
                bytesWritten, PR_GetOSError());
        } else {
            if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
        } 

        PR_Close(newSock);
        PR_AtomicDecrement(&workerThreadsBusy);
    }
}
/* Blocking I/O */
static void ServerB(void *arg)
{
    PRFileDesc *listenSock = (PRFileDesc *) arg;
    PRFileDesc *sock;
    char buf[BUFFER_SIZE];
    PRInt32 nbytes;
    int i;
    int j;

    sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
    if (NULL == sock) {
        fprintf(stderr, "PR_Accept failed\n");
        exit(1);
    }

    for (i = 0; i < iterations; i++) {
        memset(buf, 0, sizeof(buf));
        nbytes = PR_Recv(sock, buf, recv_amount[i],
                PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Recv failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "server: peeked expected data\n");

        memset(buf, 0, sizeof(buf));
        nbytes = PR_Recv(sock, buf, recv_amount[i],
                PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Recv failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "server: peeked expected data\n");

        memset(buf, 0, sizeof(buf));
        nbytes = PR_Recv(sock, buf, recv_amount[i],
                0, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Recv failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "server: received expected data\n");

        PR_Sleep(PR_SecondsToInterval(1));
        memset(buf, 2*i+1, send_amount[i]);
        nbytes = PR_Send(sock, buf, send_amount[i],
                0, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Send failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
            exit(1);
        }
    }
    if (PR_Close(sock) == PR_FAILURE) {
        fprintf(stderr, "PR_Close failed\n");
        exit(1);
    }
}
Esempio n. 30
0
static void PR_CALLBACK Server(void *arg)
{
    PRStatus rv;
    PRInt32 ready;
    PRUint8 buffer[100];
    PRFileDesc *service;
    PRUintn empty_flags = 0;
    struct PRPollDesc polldesc;
    PRIntn bytes_read, bytes_sent;
    PRFileDesc *stack = (PRFileDesc*)arg;
    PRNetAddr client_address;

    do
    {
        if (verbosity > chatty)
            PR_fprintf(logFile, "Server accepting connection\n");
        service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
        if (verbosity > chatty)
            PR_fprintf(logFile, "Server accept status [0x%p]\n", service);
        if ((NULL == service) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
        {
            polldesc.fd = stack;
            polldesc.out_flags = 0;
            polldesc.in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
            ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
            if ((1 != ready)  /* if not 1, then we're dead */
            || (0 == (polldesc.in_flags & polldesc.out_flags)))
                { PR_NOT_REACHED("Whoa!"); break; }
        }
    } while (NULL == service);
    PR_ASSERT(NULL != service);
        
    if (verbosity > quiet)
        PR_fprintf(logFile, "Server accepting connection\n");

    do
    {
        bytes_read = 0;
        do
        {
            if (verbosity > chatty)
                PR_fprintf(
                    logFile, "Server receiving %d bytes\n",
                    sizeof(buffer) - bytes_read);
            ready = PR_Recv(
                service, buffer + bytes_read, sizeof(buffer) - bytes_read,
                empty_flags, PR_INTERVAL_NO_TIMEOUT);
            if (verbosity > chatty)
                PR_fprintf(logFile, "Server receive status [%d]\n", ready);
            if (0 < ready) bytes_read += ready;
            else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
            {
                polldesc.fd = service;
                polldesc.out_flags = 0;
                polldesc.in_flags = PR_POLL_READ;
                ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
                if ((1 != ready)  /* if not 1, then we're dead */
                || (0 == (polldesc.in_flags & polldesc.out_flags)))
                    { PR_NOT_REACHED("Whoa!"); break; }
            }
            else break;
        } while (bytes_read < sizeof(buffer));

        if (0 != bytes_read)
        {
            if (verbosity > chatty)
                PR_fprintf(logFile, "Server received %d bytes\n", bytes_read);
            PR_ASSERT(bytes_read > 0);

            bytes_sent = 0;
            do
            {
                ready = PR_Send(
                    service, buffer + bytes_sent, bytes_read - bytes_sent,
                    empty_flags, PR_INTERVAL_NO_TIMEOUT);
                if (0 < ready)
                {
                    bytes_sent += ready;
                }
                else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
                {
                    polldesc.fd = service;
                    polldesc.out_flags = 0;
                    polldesc.in_flags = PR_POLL_WRITE;
                    ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
                    if ((1 != ready)  /* if not 1, then we're dead */
                    || (0 == (polldesc.in_flags & polldesc.out_flags)))
                        { PR_NOT_REACHED("Whoa!"); break; }
                }
                else break;
            } while (bytes_sent < bytes_read);
            PR_ASSERT(bytes_read == bytes_sent);
            if (verbosity > chatty)
                PR_fprintf(logFile, "Server sent %d bytes\n", bytes_sent);
        }
    } while (0 != bytes_read);

    if (verbosity > quiet)
        PR_fprintf(logFile, "Server shutting down stack\n");
    rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
    rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);

}  /* Server */