nsprpub/pr/tests/socket.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/tests/socket.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2322 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/***********************************************************************
    1.10 +**
    1.11 +** Name: socket.c
    1.12 +**
    1.13 +** Description: Test socket functionality.
    1.14 +**
    1.15 +** Modification History:
    1.16 +*/
    1.17 +#include "primpl.h"
    1.18 +
    1.19 +#include "plgetopt.h"
    1.20 +
    1.21 +#include <stdio.h>
    1.22 +#include <string.h>
    1.23 +#include <errno.h>
    1.24 +#ifdef XP_UNIX
    1.25 +#include <sys/mman.h>
    1.26 +#endif
    1.27 +#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
    1.28 +#include <pthread.h>
    1.29 +#endif
    1.30 +
    1.31 +#ifdef WIN32
    1.32 +#include <process.h>
    1.33 +#endif
    1.34 +
    1.35 +static int _debug_on = 0;
    1.36 +static int test_cancelio = 0;
    1.37 +
    1.38 +#include "obsolete/prsem.h"
    1.39 +
    1.40 +#ifdef XP_PC
    1.41 +#define mode_t int
    1.42 +#endif
    1.43 +
    1.44 +#define DPRINTF(arg) if (_debug_on) printf arg
    1.45 +
    1.46 +#ifdef XP_PC
    1.47 +char *TEST_DIR = "prdir";
    1.48 +char *SMALL_FILE_NAME = "prsmallf";
    1.49 +char *LARGE_FILE_NAME = "prlargef";
    1.50 +#elif defined(SYMBIAN)
    1.51 +char *TEST_DIR = "c:\\data\\prsocket";
    1.52 +char *SMALL_FILE_NAME = "c:\\data\\prsocket\\small_file";
    1.53 +char *LARGE_FILE_NAME = "c:\\data\\prsocket\\large_file";
    1.54 +#else
    1.55 +char *TEST_DIR = "/tmp/prsocket_test_dir";
    1.56 +char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file";
    1.57 +char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file";
    1.58 +#endif
    1.59 +#define SMALL_FILE_SIZE				(3 * 1024)        /* 3 KB        */
    1.60 +#define SMALL_FILE_OFFSET_1			(512)
    1.61 +#define SMALL_FILE_LEN_1			(1 * 1024)        /* 1 KB        */
    1.62 +#define SMALL_FILE_OFFSET_2			(75)
    1.63 +#define SMALL_FILE_LEN_2			(758)
    1.64 +#define SMALL_FILE_OFFSET_3			(1024)
    1.65 +#define SMALL_FILE_LEN_3			(SMALL_FILE_SIZE - SMALL_FILE_OFFSET_3)
    1.66 +#define SMALL_FILE_HEADER_SIZE    	(64)            /* 64 bytes    */
    1.67 +#define SMALL_FILE_TRAILER_SIZE   	(128)           /* 128 bytes    */
    1.68 +
    1.69 +#define LARGE_FILE_SIZE				(3 * 1024 * 1024)    /* 3 MB        */
    1.70 +#define LARGE_FILE_OFFSET_1			(0)
    1.71 +#define LARGE_FILE_LEN_1			(2 * 1024 * 1024)    /* 2 MB        */
    1.72 +#define LARGE_FILE_OFFSET_2			(64)
    1.73 +#define LARGE_FILE_LEN_2			(1 * 1024 * 1024 + 75)
    1.74 +#define LARGE_FILE_OFFSET_3			(2 * 1024 * 1024 - 128)
    1.75 +#define LARGE_FILE_LEN_3			(LARGE_FILE_SIZE - LARGE_FILE_OFFSET_3)
    1.76 +#define LARGE_FILE_OFFSET_4			PR_GetPageSize()
    1.77 +#define LARGE_FILE_LEN_4			769
    1.78 +#define LARGE_FILE_HEADER_SIZE    	(512)
    1.79 +#define LARGE_FILE_TRAILER_SIZE   	(64)
    1.80 +
    1.81 +#define    BUF_DATA_SIZE    (2 * 1024)
    1.82 +#define TCP_MESG_SIZE    1024
    1.83 +/*
    1.84 + * set UDP datagram size small enough that datagrams sent to a port on the
    1.85 + * local host will not be lost
    1.86 + */
    1.87 +#define UDP_DGRAM_SIZE            128
    1.88 +#define NUM_TCP_CLIENTS            5	/* for a listen queue depth of 5 */
    1.89 +#define NUM_UDP_CLIENTS            10
    1.90 +
    1.91 +#ifdef SYMBIAN
    1.92 +#define NUM_TRANSMITFILE_CLIENTS    1
    1.93 +#else
    1.94 +#define NUM_TRANSMITFILE_CLIENTS    4
    1.95 +#endif
    1.96 +
    1.97 +#define NUM_TCP_CONNECTIONS_PER_CLIENT    5
    1.98 +#define NUM_TCP_MESGS_PER_CONNECTION    10
    1.99 +#define NUM_UDP_DATAGRAMS_PER_CLIENT    5
   1.100 +#define TCP_SERVER_PORT            10000
   1.101 +#define UDP_SERVER_PORT            TCP_SERVER_PORT
   1.102 +#define SERVER_MAX_BIND_COUNT        100
   1.103 +
   1.104 +#ifdef WINCE
   1.105 +#define perror(s)
   1.106 +#endif
   1.107 +
   1.108 +static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
   1.109 +static PRInt32 num_udp_clients = NUM_UDP_CLIENTS;
   1.110 +static PRInt32 num_transmitfile_clients = NUM_TRANSMITFILE_CLIENTS;
   1.111 +static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
   1.112 +static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
   1.113 +static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
   1.114 +static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT;
   1.115 +static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE;
   1.116 +
   1.117 +static PRInt32 thread_count;
   1.118 +PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET;
   1.119 +
   1.120 +/* an I/O layer that uses the emulated senfile method */
   1.121 +static PRDescIdentity emuSendFileIdentity;
   1.122 +static PRIOMethods emuSendFileMethods;
   1.123 +
   1.124 +int failed_already=0;
   1.125 +typedef struct buffer {
   1.126 +    char    data[BUF_DATA_SIZE];
   1.127 +} buffer;
   1.128 +
   1.129 +PRNetAddr tcp_server_addr, udp_server_addr;
   1.130 +
   1.131 +typedef struct Serve_Client_Param {
   1.132 +    PRFileDesc *sockfd;    /* socket to read from/write to    */
   1.133 +    PRInt32    datalen;    /* bytes of data transfered in each read/write */
   1.134 +} Serve_Client_Param;
   1.135 +
   1.136 +typedef struct Server_Param {
   1.137 +    PRSemaphore *addr_sem;    /* sem to post on, after setting up the address */
   1.138 +    PRMonitor *exit_mon;    /* monitor to signal on exit            */
   1.139 +    PRInt32 *exit_counter;    /* counter to decrement, before exit        */
   1.140 +    PRInt32    datalen;    /* bytes of data transfered in each read/write    */
   1.141 +} Server_Param;
   1.142 +
   1.143 +
   1.144 +typedef struct Client_Param {
   1.145 +    PRNetAddr server_addr;
   1.146 +    PRMonitor *exit_mon;    /* monitor to signal on exit */
   1.147 +    PRInt32 *exit_counter;    /* counter to decrement, before exit */
   1.148 +    PRInt32    datalen;
   1.149 +    PRInt32    udp_connect;    /* if set clients connect udp sockets */
   1.150 +} Client_Param;
   1.151 +
   1.152 +/* the sendfile method in emuSendFileMethods */
   1.153 +static PRInt32 PR_CALLBACK
   1.154 +emu_SendFile(PRFileDesc *sd, PRSendFileData *sfd,
   1.155 +    PRTransmitFileFlags flags, PRIntervalTime timeout)
   1.156 +{
   1.157 +    return PR_EmulateSendFile(sd, sfd, flags, timeout);
   1.158 +}
   1.159 +
   1.160 +/* the transmitfile method in emuSendFileMethods */
   1.161 +static PRInt32 PR_CALLBACK
   1.162 +emu_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers,
   1.163 +    PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
   1.164 +{
   1.165 +    PRSendFileData sfd;
   1.166 +
   1.167 +    sfd.fd = fd;
   1.168 +    sfd.file_offset = 0;
   1.169 +    sfd.file_nbytes = 0;
   1.170 +    sfd.header = headers;
   1.171 +    sfd.hlen = hlen;
   1.172 +    sfd.trailer = NULL;
   1.173 +    sfd.tlen = 0;
   1.174 +    return emu_SendFile(sd, &sfd, flags, timeout);
   1.175 +}
   1.176 +
   1.177 +/*
   1.178 + * readn
   1.179 + *    read data from sockfd into buf
   1.180 + */
   1.181 +static PRInt32
   1.182 +readn(PRFileDesc *sockfd, char *buf, int len)
   1.183 +{
   1.184 +    int rem;
   1.185 +    int bytes;
   1.186 +    int offset = 0;
   1.187 +	int err;
   1.188 +	PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
   1.189 +
   1.190 +	if (test_cancelio)
   1.191 +		timeout = PR_SecondsToInterval(2);
   1.192 +
   1.193 +    for (rem=len; rem; offset += bytes, rem -= bytes) {
   1.194 +        DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",
   1.195 +            PR_GetCurrentThread(), rem));
   1.196 +retry:
   1.197 +        bytes = PR_Recv(sockfd, buf + offset, rem, 0,
   1.198 +            	timeout);
   1.199 +        DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",
   1.200 +            PR_GetCurrentThread(), bytes));
   1.201 +        if (bytes < 0) {
   1.202 +#ifdef WINNT
   1.203 +			printf("PR_Recv: error = %d oserr = %d\n",(err = PR_GetError()),
   1.204 +									PR_GetOSError());
   1.205 +			if ((test_cancelio) && (err == PR_IO_TIMEOUT_ERROR)) {
   1.206 +				if (PR_NT_CancelIo(sockfd) != PR_SUCCESS)
   1.207 +					printf("PR_NT_CancelIO: error = %d\n",PR_GetError());
   1.208 +				timeout = PR_INTERVAL_NO_TIMEOUT;
   1.209 +				goto retry;
   1.210 +			}
   1.211 +#endif
   1.212 +			return -1;
   1.213 +		}	
   1.214 +    }
   1.215 +    return len;
   1.216 +}
   1.217 +
   1.218 +/*
   1.219 + * writen
   1.220 + *    write data from buf to sockfd
   1.221 + */
   1.222 +static PRInt32
   1.223 +writen(PRFileDesc *sockfd, char *buf, int len)
   1.224 +{
   1.225 +    int rem;
   1.226 +    int bytes;
   1.227 +    int offset = 0;
   1.228 +
   1.229 +    for (rem=len; rem; offset += bytes, rem -= bytes) {
   1.230 +        DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
   1.231 +            PR_GetCurrentThread(), rem));
   1.232 +        bytes = PR_Send(sockfd, buf + offset, rem, 0,
   1.233 +            PR_INTERVAL_NO_TIMEOUT);
   1.234 +        DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
   1.235 +            PR_GetCurrentThread(), bytes));
   1.236 +        if (bytes <= 0)
   1.237 +            return -1;
   1.238 +    }
   1.239 +    return len;
   1.240 +}
   1.241 +
   1.242 +/*
   1.243 + * Serve_Client
   1.244 + *    Thread, started by the server, for serving a client connection.
   1.245 + *    Reads data from socket and writes it back, unmodified, and
   1.246 + *    closes the socket
   1.247 + */
   1.248 +static void PR_CALLBACK
   1.249 +Serve_Client(void *arg)
   1.250 +{
   1.251 +    Serve_Client_Param *scp = (Serve_Client_Param *) arg;
   1.252 +    PRFileDesc *sockfd;
   1.253 +    buffer *in_buf;
   1.254 +    PRInt32 bytes, j;
   1.255 +
   1.256 +    sockfd = scp->sockfd;
   1.257 +    bytes = scp->datalen;
   1.258 +    in_buf = PR_NEW(buffer);
   1.259 +    if (in_buf == NULL) {
   1.260 +        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   1.261 +        failed_already=1;
   1.262 +        goto exit;
   1.263 +    }
   1.264 +
   1.265 +
   1.266 +    for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
   1.267 +        /*
   1.268 +         * Read data from client and send it back to the client unmodified
   1.269 +         */
   1.270 +        if (readn(sockfd, in_buf->data, bytes) < bytes) {
   1.271 +            fprintf(stderr,"prsocket_test: ERROR - Serve_Client:readn\n");
   1.272 +            failed_already=1;
   1.273 +            goto exit;
   1.274 +        }
   1.275 +        /* Shutdown only RCV will cause error on Symbian OS */
   1.276 +#if !defined(SYMBIAN)
   1.277 +        /*
   1.278 +         * shutdown reads, after the last read
   1.279 +         */
   1.280 +        if (j == num_tcp_mesgs_per_connection - 1)
   1.281 +            if (PR_Shutdown(sockfd, PR_SHUTDOWN_RCV) < 0) {
   1.282 +                fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
   1.283 +            }
   1.284 +#endif
   1.285 +        DPRINTF(("Serve_Client [0x%lx]: inbuf[0] = 0x%lx\n",PR_GetCurrentThread(),
   1.286 +            (*((int *) in_buf->data))));
   1.287 +        if (writen(sockfd, in_buf->data, bytes) < bytes) {
   1.288 +            fprintf(stderr,"prsocket_test: ERROR - Serve_Client:writen\n");
   1.289 +            failed_already=1;
   1.290 +            goto exit;
   1.291 +        }
   1.292 +    }
   1.293 +    /*
   1.294 +     * shutdown reads and writes
   1.295 +     */
   1.296 +    if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
   1.297 +        fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
   1.298 +        failed_already=1;
   1.299 +    }
   1.300 +
   1.301 +exit:
   1.302 +    PR_Close(sockfd);
   1.303 +    if (in_buf) {
   1.304 +        PR_DELETE(in_buf);
   1.305 +    }
   1.306 +}
   1.307 +
   1.308 +PRThread* create_new_thread(PRThreadType type,
   1.309 +							void (*start)(void *arg),
   1.310 +							void *arg,
   1.311 +							PRThreadPriority priority,
   1.312 +							PRThreadScope scope,
   1.313 +							PRThreadState state,
   1.314 +							PRUint32 stackSize, PRInt32 index)
   1.315 +{
   1.316 +PRInt32 native_thread = 0;
   1.317 +
   1.318 +	PR_ASSERT(state == PR_UNJOINABLE_THREAD);
   1.319 +#if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32)
   1.320 +	switch(index %  4) {
   1.321 +		case 0:
   1.322 +			scope = (PR_LOCAL_THREAD);
   1.323 +			break;
   1.324 +		case 1:
   1.325 +			scope = (PR_GLOBAL_THREAD);
   1.326 +			break;
   1.327 +		case 2:
   1.328 +			scope = (PR_GLOBAL_BOUND_THREAD);
   1.329 +			break;
   1.330 +		case 3:
   1.331 +			native_thread = 1;
   1.332 +			break;
   1.333 +		default:
   1.334 +			PR_ASSERT(!"Invalid scope");
   1.335 +			break;
   1.336 +	}
   1.337 +	if (native_thread) {
   1.338 +#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
   1.339 +		pthread_t tid;
   1.340 +		if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg))
   1.341 +			return((PRThread *) tid);
   1.342 +		else
   1.343 +			return (NULL);
   1.344 +#else
   1.345 +		HANDLE thandle;
   1.346 +		unsigned tid;
   1.347 +		
   1.348 +		thandle = (HANDLE) _beginthreadex(
   1.349 +						NULL,
   1.350 +						stackSize,
   1.351 +						(unsigned (__stdcall *)(void *))start,
   1.352 +						arg,
   1.353 +						STACK_SIZE_PARAM_IS_A_RESERVATION,
   1.354 +						&tid);		
   1.355 +		return((PRThread *) thandle);
   1.356 +#endif
   1.357 +	} else {
   1.358 +		return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
   1.359 +	}
   1.360 +#else
   1.361 +	return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
   1.362 +#endif
   1.363 +}
   1.364 +
   1.365 +/*
   1.366 + * TCP Server
   1.367 + *    Server Thread
   1.368 + *    Bind an address to a socket and listen for incoming connections
   1.369 + *    Start a Serve_Client thread for each incoming connection.
   1.370 + */
   1.371 +static void PR_CALLBACK
   1.372 +TCP_Server(void *arg)
   1.373 +{
   1.374 +    PRThread *t;
   1.375 +    Server_Param *sp = (Server_Param *) arg;
   1.376 +    Serve_Client_Param *scp;
   1.377 +    PRFileDesc *sockfd, *newsockfd;
   1.378 +    PRNetAddr netaddr;
   1.379 +    PRInt32 i;
   1.380 +    /*
   1.381 +     * Create a tcp socket
   1.382 +     */
   1.383 +	if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) {
   1.384 +        fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
   1.385 +        goto exit;
   1.386 +    }
   1.387 +    memset(&netaddr, 0 , sizeof(netaddr));
   1.388 +	
   1.389 +	if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT,
   1.390 +									&netaddr) == PR_FAILURE) {
   1.391 +        fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   1.392 +        goto exit;
   1.393 +	}
   1.394 +    /*
   1.395 +     * try a few times to bind server's address, if addresses are in
   1.396 +     * use
   1.397 +     */
   1.398 +    i = 0;
   1.399 +	
   1.400 +    while (PR_Bind(sockfd, &netaddr) < 0) {
   1.401 +        if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
   1.402 +            netaddr.inet.port += 2;
   1.403 +            if (i++ < SERVER_MAX_BIND_COUNT)
   1.404 +                continue;
   1.405 +        }
   1.406 +        fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
   1.407 +        perror("PR_Bind");
   1.408 +        failed_already=1;
   1.409 +        goto exit;
   1.410 +    }
   1.411 +
   1.412 +    if (PR_Listen(sockfd, 32) < 0) {
   1.413 +        fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n");
   1.414 +        failed_already=1;
   1.415 +        goto exit;
   1.416 +    }
   1.417 +
   1.418 +    if (PR_GetSockName(sockfd, &netaddr) < 0) {
   1.419 +        fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
   1.420 +        failed_already=1;
   1.421 +        goto exit;
   1.422 +    }
   1.423 +
   1.424 +    DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
   1.425 +        netaddr.inet.ip, netaddr.inet.port));
   1.426 +	if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
   1.427 +									PR_ntohs(PR_NetAddrInetPort(&netaddr)),
   1.428 +									&tcp_server_addr) == PR_FAILURE) {
   1.429 +        fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   1.430 +        goto exit;
   1.431 +	}
   1.432 +	if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
   1.433 +		PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
   1.434 +								&tcp_server_addr.ipv6.ip);
   1.435 +
   1.436 +    /*
   1.437 +     * Wake up parent thread because server address is bound and made
   1.438 +     * available in the global variable 'tcp_server_addr'
   1.439 +     */
   1.440 +    PR_PostSem(sp->addr_sem);
   1.441 +
   1.442 +    for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) {
   1.443 +        /* test both null and non-null 'addr' argument to PR_Accept */
   1.444 +        PRNetAddr *addrp = (i%2 ? &netaddr: NULL);
   1.445 +
   1.446 +    DPRINTF(("TCP_Server: Accepting connection\n"));
   1.447 +        if ((newsockfd = PR_Accept(sockfd, addrp,
   1.448 +            PR_INTERVAL_NO_TIMEOUT)) == NULL) {
   1.449 +            fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n");
   1.450 +            goto exit;
   1.451 +        }
   1.452 +    DPRINTF(("TCP_Server: Accepted connection\n"));
   1.453 +        scp = PR_NEW(Serve_Client_Param);
   1.454 +        if (scp == NULL) {
   1.455 +            fprintf(stderr,"prsocket_test: PR_NEW failed\n");
   1.456 +            goto exit;
   1.457 +        }
   1.458 +
   1.459 +        /*
   1.460 +         * Start a Serve_Client thread for each incoming connection
   1.461 +         */
   1.462 +        scp->sockfd = newsockfd;
   1.463 +        scp->datalen = sp->datalen;
   1.464 +
   1.465 +        t = create_new_thread(PR_USER_THREAD,
   1.466 +            Serve_Client, (void *)scp, 
   1.467 +            PR_PRIORITY_NORMAL,
   1.468 +            PR_LOCAL_THREAD,
   1.469 +            PR_UNJOINABLE_THREAD,
   1.470 +            0, i);
   1.471 +        if (t == NULL) {
   1.472 +            fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
   1.473 +            failed_already=1;
   1.474 +            goto exit;
   1.475 +        }
   1.476 +        DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t));
   1.477 +    }
   1.478 +
   1.479 +exit:
   1.480 +    if (sockfd) {
   1.481 +        PR_Close(sockfd);
   1.482 +    }
   1.483 +
   1.484 +    /*
   1.485 +     * Decrement exit_counter and notify parent thread
   1.486 +     */
   1.487 +
   1.488 +    PR_EnterMonitor(sp->exit_mon);
   1.489 +    --(*sp->exit_counter);
   1.490 +    PR_Notify(sp->exit_mon);
   1.491 +    PR_ExitMonitor(sp->exit_mon);
   1.492 +    DPRINTF(("TCP_Server [0x%lx] exiting\n", PR_GetCurrentThread()));
   1.493 +}
   1.494 +
   1.495 +/*
   1.496 + * UDP Server
   1.497 + *    Server Thread
   1.498 + *    Bind an address to a socket, read data from clients and send data
   1.499 + *    back to clients
   1.500 + */
   1.501 +static void PR_CALLBACK
   1.502 +UDP_Server(void *arg)
   1.503 +{
   1.504 +    Server_Param *sp = (Server_Param *) arg;
   1.505 +    PRFileDesc *sockfd;
   1.506 +    buffer *in_buf;
   1.507 +    PRNetAddr netaddr;
   1.508 +    PRInt32 bytes, i, rv = 0;
   1.509 +
   1.510 +
   1.511 +    bytes = sp->datalen;
   1.512 +    /*
   1.513 +     * Create a udp socket
   1.514 +     */
   1.515 +	if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) {
   1.516 +        fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n");
   1.517 +        failed_already=1;
   1.518 +        return;
   1.519 +    }
   1.520 +    memset(&netaddr, 0 , sizeof(netaddr));
   1.521 +	if (PR_SetNetAddr(PR_IpAddrAny, server_domain, UDP_SERVER_PORT,
   1.522 +									&netaddr) == PR_FAILURE) {
   1.523 +        fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   1.524 +        failed_already=1;
   1.525 +        return;
   1.526 +	}
   1.527 +    /*
   1.528 +     * try a few times to bind server's address, if addresses are in
   1.529 +     * use
   1.530 +     */
   1.531 +    i = 0;
   1.532 +    while (PR_Bind(sockfd, &netaddr) < 0) {
   1.533 +        if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
   1.534 +            netaddr.inet.port += 2;
   1.535 +            if (i++ < SERVER_MAX_BIND_COUNT)
   1.536 +                continue;
   1.537 +        }
   1.538 +        fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
   1.539 +        perror("PR_Bind");
   1.540 +        failed_already=1;
   1.541 +        return;
   1.542 +    }
   1.543 +
   1.544 +    if (PR_GetSockName(sockfd, &netaddr) < 0) {
   1.545 +        fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
   1.546 +        failed_already=1;
   1.547 +        return;
   1.548 +    }
   1.549 +
   1.550 +    DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
   1.551 +        netaddr.inet.ip, netaddr.inet.port));
   1.552 +    /*
   1.553 +     * We can't use the IP address returned by PR_GetSockName in
   1.554 +     * netaddr.inet.ip because netaddr.inet.ip is returned
   1.555 +     * as 0 (= PR_INADDR_ANY).
   1.556 +     */
   1.557 +
   1.558 +	if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
   1.559 +									PR_ntohs(PR_NetAddrInetPort(&netaddr)),
   1.560 +									&udp_server_addr) == PR_FAILURE) {
   1.561 +        fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   1.562 +        failed_already=1;
   1.563 +        return;
   1.564 +	}
   1.565 +	if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
   1.566 +		PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
   1.567 +								&udp_server_addr.ipv6.ip);
   1.568 +		
   1.569 +    /*
   1.570 +     * Wake up parent thread because server address is bound and made
   1.571 +     * available in the global variable 'udp_server_addr'
   1.572 +     */
   1.573 +    PR_PostSem(sp->addr_sem);
   1.574 +
   1.575 +    bytes = sp->datalen;
   1.576 +    in_buf = PR_NEW(buffer);
   1.577 +    if (in_buf == NULL) {
   1.578 +        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   1.579 +        failed_already=1;
   1.580 +        return;
   1.581 +    }
   1.582 +    /*
   1.583 +     * Receive datagrams from clients and send them back, unmodified, to the
   1.584 +     * clients
   1.585 +     */
   1.586 +    memset(&netaddr, 0 , sizeof(netaddr));
   1.587 +    for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) {
   1.588 +        DPRINTF(("UDP_Server: calling PR_RecvFrom client  - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
   1.589 +            netaddr.inet.ip, netaddr.inet.port, bytes, in_buf->data,
   1.590 +            in_buf->data[0]));
   1.591 +
   1.592 +        rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
   1.593 +            PR_INTERVAL_NO_TIMEOUT);
   1.594 +        DPRINTF(("UDP_Server: PR_RecvFrom client  - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
   1.595 +            netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data,
   1.596 +            in_buf->data[0]));
   1.597 +        if (rv != bytes) {
   1.598 +            return;
   1.599 +        }
   1.600 +        rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr,
   1.601 +            PR_INTERVAL_NO_TIMEOUT);
   1.602 +        if (rv != bytes) {
   1.603 +            return;
   1.604 +        }
   1.605 +    }
   1.606 +
   1.607 +    PR_DELETE(in_buf);
   1.608 +    PR_Close(sockfd);
   1.609 +
   1.610 +    /*
   1.611 +     * Decrement exit_counter and notify parent thread
   1.612 +     */
   1.613 +    PR_EnterMonitor(sp->exit_mon);
   1.614 +    --(*sp->exit_counter);
   1.615 +    PR_Notify(sp->exit_mon);
   1.616 +    PR_ExitMonitor(sp->exit_mon);
   1.617 +    DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread()));
   1.618 +}
   1.619 +
   1.620 +/*
   1.621 + * TCP_Client
   1.622 + *    Client Thread
   1.623 + *    Connect to the server at the address specified in the argument.
   1.624 + *    Fill in a buffer, write data to server, read it back and check
   1.625 + *    for data corruption.
   1.626 + *    Close the socket for server connection
   1.627 + */
   1.628 +static void PR_CALLBACK
   1.629 +TCP_Client(void *arg)
   1.630 +{
   1.631 +    Client_Param *cp = (Client_Param *) arg;
   1.632 +    PRFileDesc *sockfd;
   1.633 +    buffer *in_buf, *out_buf;
   1.634 +    union PRNetAddr netaddr;
   1.635 +    PRInt32 bytes, i, j;
   1.636 +
   1.637 +
   1.638 +    bytes = cp->datalen;
   1.639 +    out_buf = PR_NEW(buffer);
   1.640 +    if (out_buf == NULL) {
   1.641 +        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   1.642 +        failed_already=1;
   1.643 +        return;
   1.644 +    }
   1.645 +    in_buf = PR_NEW(buffer);
   1.646 +    if (in_buf == NULL) {
   1.647 +        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   1.648 +        failed_already=1;
   1.649 +        return;
   1.650 +    }
   1.651 +    netaddr = cp->server_addr;
   1.652 +
   1.653 +    for (i = 0; i < num_tcp_connections_per_client; i++) {
   1.654 +        if ((sockfd = PR_OpenTCPSocket(client_domain)) == NULL) {
   1.655 +            fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n");
   1.656 +            failed_already=1;
   1.657 +            return;
   1.658 +        }
   1.659 +        if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
   1.660 +        	fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n",
   1.661 +            		PR_GetError(), PR_GetOSError());
   1.662 +            failed_already=1;
   1.663 +            return;
   1.664 +        }
   1.665 +        for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
   1.666 +            /*
   1.667 +             * fill in random data
   1.668 +             */
   1.669 +            memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes);
   1.670 +            /*
   1.671 +             * write to server
   1.672 +             */
   1.673 +#ifdef WINNT
   1.674 +			if (test_cancelio && (j == 0))
   1.675 +				PR_Sleep(PR_SecondsToInterval(12));
   1.676 +#endif
   1.677 +            if (writen(sockfd, out_buf->data, bytes) < bytes) {
   1.678 +                fprintf(stderr,"prsocket_test: ERROR - TCP_Client:writen\n");
   1.679 +                failed_already=1;
   1.680 +                return;
   1.681 +            }
   1.682 +            DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
   1.683 +                PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
   1.684 +            if (readn(sockfd, in_buf->data, bytes) < bytes) {
   1.685 +                fprintf(stderr,"prsocket_test: ERROR - TCP_Client:readn\n");
   1.686 +                failed_already=1;
   1.687 +                return;
   1.688 +            }
   1.689 +            /*
   1.690 +             * verify the data read
   1.691 +             */
   1.692 +            if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
   1.693 +                fprintf(stderr,"prsocket_test: ERROR - data corruption\n");
   1.694 +                failed_already=1;
   1.695 +                return;
   1.696 +            }
   1.697 +        }
   1.698 +        /*
   1.699 +         * shutdown reads and writes
   1.700 +         */
   1.701 +        if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
   1.702 +            fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
   1.703 +#if defined(SYMBIAN)
   1.704 +            if (EPIPE != errno)
   1.705 +#endif
   1.706 +            failed_already=1;
   1.707 +        }
   1.708 +        PR_Close(sockfd);
   1.709 +    }
   1.710 +
   1.711 +    PR_DELETE(out_buf);
   1.712 +    PR_DELETE(in_buf);
   1.713 +
   1.714 +    /*
   1.715 +     * Decrement exit_counter and notify parent thread
   1.716 +     */
   1.717 +
   1.718 +    PR_EnterMonitor(cp->exit_mon);
   1.719 +    --(*cp->exit_counter);
   1.720 +    PR_Notify(cp->exit_mon);
   1.721 +    PR_ExitMonitor(cp->exit_mon);
   1.722 +    DPRINTF(("TCP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
   1.723 +}
   1.724 +
   1.725 +/*
   1.726 + * UDP_Client
   1.727 + *    Client Thread
   1.728 + *    Create a socket and bind an address 
   1.729 + *    Communicate with the server at the address specified in the argument.
   1.730 + *    Fill in a buffer, write data to server, read it back and check
   1.731 + *    for data corruption.
   1.732 + *    Close the socket
   1.733 + */
   1.734 +static void PR_CALLBACK
   1.735 +UDP_Client(void *arg)
   1.736 +{
   1.737 +    Client_Param *cp = (Client_Param *) arg;
   1.738 +    PRFileDesc *sockfd;
   1.739 +    buffer *in_buf, *out_buf;
   1.740 +    union PRNetAddr netaddr;
   1.741 +    PRInt32 bytes, i, rv;
   1.742 +
   1.743 +
   1.744 +    bytes = cp->datalen;
   1.745 +    out_buf = PR_NEW(buffer);
   1.746 +    if (out_buf == NULL) {
   1.747 +        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   1.748 +        failed_already=1;
   1.749 +        return;
   1.750 +    }
   1.751 +    in_buf = PR_NEW(buffer);
   1.752 +    if (in_buf == NULL) {
   1.753 +        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   1.754 +        failed_already=1;
   1.755 +        return;
   1.756 +    }
   1.757 +    if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) {
   1.758 +        fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n");
   1.759 +        failed_already=1;
   1.760 +        return;
   1.761 +    }
   1.762 +
   1.763 +    /*
   1.764 +     * bind an address for the client, let the system chose the port
   1.765 +     * number
   1.766 +     */
   1.767 +    memset(&netaddr, 0 , sizeof(netaddr));
   1.768 +	if (PR_SetNetAddr(PR_IpAddrAny, client_domain, 0,
   1.769 +									&netaddr) == PR_FAILURE) {
   1.770 +        fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   1.771 +        failed_already=1;
   1.772 +        return;
   1.773 +	}
   1.774 +    if (PR_Bind(sockfd, &netaddr) < 0) {
   1.775 +        fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
   1.776 +        perror("PR_Bind");
   1.777 +        return;
   1.778 +    }
   1.779 +
   1.780 +    if (PR_GetSockName(sockfd, &netaddr) < 0) {
   1.781 +        fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
   1.782 +        failed_already=1;
   1.783 +        return;
   1.784 +    }
   1.785 +
   1.786 +    DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
   1.787 +        netaddr.inet.ip, netaddr.inet.port));
   1.788 +
   1.789 +    netaddr = cp->server_addr;
   1.790 +
   1.791 +    if (cp->udp_connect) {
   1.792 +        if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
   1.793 +            fprintf(stderr,"prsocket_test: PR_Connect failed\n");
   1.794 +            failed_already=1;
   1.795 +            return;
   1.796 +        }
   1.797 +    }
   1.798 +
   1.799 +    for (i = 0; i < num_udp_datagrams_per_client; i++) {
   1.800 +        /*
   1.801 +         * fill in random data
   1.802 +         */
   1.803 +        DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n",
   1.804 +            PR_GetCurrentThread(), out_buf->data, bytes));
   1.805 +        memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes);
   1.806 +        /*
   1.807 +         * write to server
   1.808 +         */
   1.809 +        if (cp->udp_connect)
   1.810 +            rv = PR_Send(sockfd, out_buf->data, bytes, 0,
   1.811 +                PR_INTERVAL_NO_TIMEOUT);
   1.812 +        else
   1.813 +            rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr,
   1.814 +                PR_INTERVAL_NO_TIMEOUT);
   1.815 +        if (rv != bytes) {
   1.816 +            return;
   1.817 +        }
   1.818 +        DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
   1.819 +            PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
   1.820 +        if (cp->udp_connect)
   1.821 +            rv = PR_Recv(sockfd, in_buf->data, bytes, 0,
   1.822 +                PR_INTERVAL_NO_TIMEOUT);
   1.823 +        else
   1.824 +            rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
   1.825 +                PR_INTERVAL_NO_TIMEOUT);
   1.826 +        if (rv != bytes) {
   1.827 +            return;
   1.828 +        }
   1.829 +        DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n",
   1.830 +            PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data))));
   1.831 +        /*
   1.832 +         * verify the data read
   1.833 +         */
   1.834 +        if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
   1.835 +            fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n");
   1.836 +            failed_already=1;
   1.837 +            return;
   1.838 +        }
   1.839 +    }
   1.840 +    PR_Close(sockfd);
   1.841 +
   1.842 +    PR_DELETE(in_buf);
   1.843 +    PR_DELETE(out_buf);
   1.844 +
   1.845 +    /*
   1.846 +     * Decrement exit_counter and notify parent thread
   1.847 +     */
   1.848 +
   1.849 +    PR_EnterMonitor(cp->exit_mon);
   1.850 +    --(*cp->exit_counter);
   1.851 +    PR_Notify(cp->exit_mon);
   1.852 +    PR_ExitMonitor(cp->exit_mon);
   1.853 +    PR_DELETE(cp);
   1.854 +    DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
   1.855 +}
   1.856 +
   1.857 +/*
   1.858 + * TCP_Socket_Client_Server_Test    - concurrent server test
   1.859 + *    
   1.860 + *    One server and several clients are started
   1.861 + *    Each client connects to the server and sends a chunk of data
   1.862 + *    For each connection, server starts another thread to read the data
   1.863 + *    from the client and send it back to the client, unmodified.
   1.864 + *    Each client checks that data received from server is same as the
   1.865 + *    data it sent to the server.
   1.866 + *
   1.867 + */
   1.868 +
   1.869 +static PRInt32
   1.870 +TCP_Socket_Client_Server_Test(void)
   1.871 +{
   1.872 +    int i;
   1.873 +    PRThread *t;
   1.874 +    PRSemaphore *server_sem;
   1.875 +    Server_Param *sparamp;
   1.876 +    Client_Param *cparamp;
   1.877 +    PRMonitor *mon2;
   1.878 +    PRInt32    datalen;
   1.879 +
   1.880 +
   1.881 +    datalen = tcp_mesg_size;
   1.882 +    thread_count = 0;
   1.883 +    /*
   1.884 +     * start the server thread
   1.885 +     */
   1.886 +    sparamp = PR_NEW(Server_Param);
   1.887 +    if (sparamp == NULL) {
   1.888 +        fprintf(stderr,"prsocket_test: PR_NEW failed\n");
   1.889 +        failed_already=1;
   1.890 +        return -1;
   1.891 +    }
   1.892 +    server_sem = PR_NewSem(0);
   1.893 +    if (server_sem == NULL) {
   1.894 +        fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
   1.895 +        failed_already=1;
   1.896 +        return -1;
   1.897 +    }
   1.898 +    mon2 = PR_NewMonitor();
   1.899 +    if (mon2 == NULL) {
   1.900 +        fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
   1.901 +        failed_already=1;
   1.902 +        return -1;
   1.903 +    }
   1.904 +    PR_EnterMonitor(mon2);
   1.905 +
   1.906 +    sparamp->addr_sem = server_sem;
   1.907 +    sparamp->exit_mon = mon2;
   1.908 +    sparamp->exit_counter = &thread_count;
   1.909 +    sparamp->datalen = datalen;
   1.910 +    t = PR_CreateThread(PR_USER_THREAD,
   1.911 +        TCP_Server, (void *)sparamp, 
   1.912 +        PR_PRIORITY_NORMAL,
   1.913 +        PR_LOCAL_THREAD,
   1.914 +        PR_UNJOINABLE_THREAD,
   1.915 +        0);
   1.916 +    if (t == NULL) {
   1.917 +        fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
   1.918 +        failed_already=1;
   1.919 +        return -1;
   1.920 +    }
   1.921 +    DPRINTF(("Created TCP server = 0x%lx\n", t));
   1.922 +    thread_count++;
   1.923 +
   1.924 +    /*
   1.925 +     * wait till the server address is setup
   1.926 +     */
   1.927 +    PR_WaitSem(server_sem);
   1.928 +
   1.929 +    /*
   1.930 +     * Now start a bunch of client threads
   1.931 +     */
   1.932 +
   1.933 +    cparamp = PR_NEW(Client_Param);
   1.934 +    if (cparamp == NULL) {
   1.935 +        fprintf(stderr,"prsocket_test: PR_NEW failed\n");
   1.936 +        failed_already=1;
   1.937 +        return -1;
   1.938 +    }
   1.939 +    cparamp->server_addr = tcp_server_addr;
   1.940 +    cparamp->exit_mon = mon2;
   1.941 +    cparamp->exit_counter = &thread_count;
   1.942 +    cparamp->datalen = datalen;
   1.943 +    for (i = 0; i < num_tcp_clients; i++) {
   1.944 +        t = create_new_thread(PR_USER_THREAD,
   1.945 +            TCP_Client, (void *) cparamp,
   1.946 +            PR_PRIORITY_NORMAL,
   1.947 +            PR_LOCAL_THREAD,
   1.948 +            PR_UNJOINABLE_THREAD,
   1.949 +            0, i);
   1.950 +        if (t == NULL) {
   1.951 +            fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
   1.952 +            failed_already=1;
   1.953 +            return -1;
   1.954 +        }
   1.955 +        DPRINTF(("Created TCP client = 0x%lx\n", t));
   1.956 +        thread_count++;
   1.957 +    }
   1.958 +    /* Wait for server and client threads to exit */
   1.959 +    while (thread_count) {
   1.960 +        PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
   1.961 +        DPRINTF(("TCP Server - thread_count  = %d\n", thread_count));
   1.962 +    }
   1.963 +    PR_ExitMonitor(mon2);
   1.964 +    printf("%30s","TCP_Socket_Client_Server_Test:");
   1.965 +    printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
   1.966 +        num_tcp_clients, num_tcp_connections_per_client);
   1.967 +    printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
   1.968 +        num_tcp_mesgs_per_connection, tcp_mesg_size);
   1.969 +
   1.970 +    return 0;
   1.971 +}
   1.972 +
   1.973 +/*
   1.974 + * UDP_Socket_Client_Server_Test    - iterative server test
   1.975 + *    
   1.976 + *    One server and several clients are started
   1.977 + *    Each client connects to the server and sends a chunk of data
   1.978 + *    For each connection, server starts another thread to read the data
   1.979 + *    from the client and send it back to the client, unmodified.
   1.980 + *    Each client checks that data received from server is same as the
   1.981 + *    data it sent to the server.
   1.982 + *
   1.983 + */
   1.984 +
   1.985 +static PRInt32
   1.986 +UDP_Socket_Client_Server_Test(void)
   1.987 +{
   1.988 +    int i;
   1.989 +    PRThread *t;
   1.990 +    PRSemaphore *server_sem;
   1.991 +    Server_Param *sparamp;
   1.992 +    Client_Param *cparamp;
   1.993 +    PRMonitor *mon2;
   1.994 +    PRInt32    datalen;
   1.995 +    PRInt32    udp_connect = 1;
   1.996 +
   1.997 +
   1.998 +    datalen = udp_datagram_size;
   1.999 +    thread_count = 0;
  1.1000 +    /*
  1.1001 +     * start the server thread
  1.1002 +     */
  1.1003 +    sparamp = PR_NEW(Server_Param);
  1.1004 +    if (sparamp == NULL) {
  1.1005 +        fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1.1006 +        failed_already=1;
  1.1007 +        return -1;
  1.1008 +    }
  1.1009 +    server_sem = PR_NewSem(0);
  1.1010 +    if (server_sem == NULL) {
  1.1011 +        fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
  1.1012 +        failed_already=1;
  1.1013 +        return -1;
  1.1014 +    }
  1.1015 +    mon2 = PR_NewMonitor();
  1.1016 +    if (mon2 == NULL) {
  1.1017 +        fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
  1.1018 +        failed_already=1;
  1.1019 +        return -1;
  1.1020 +    }
  1.1021 +    PR_EnterMonitor(mon2);
  1.1022 +
  1.1023 +    sparamp->addr_sem = server_sem;
  1.1024 +    sparamp->exit_mon = mon2;
  1.1025 +    sparamp->exit_counter = &thread_count;
  1.1026 +    sparamp->datalen = datalen;
  1.1027 +    DPRINTF(("Creating UDP server"));
  1.1028 +    t = PR_CreateThread(PR_USER_THREAD,
  1.1029 +        UDP_Server, (void *)sparamp, 
  1.1030 +        PR_PRIORITY_NORMAL,
  1.1031 +        PR_LOCAL_THREAD,
  1.1032 +        PR_UNJOINABLE_THREAD,
  1.1033 +        0);
  1.1034 +    if (t == NULL) {
  1.1035 +        fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  1.1036 +        failed_already=1;
  1.1037 +        return -1;
  1.1038 +    }
  1.1039 +    thread_count++;
  1.1040 +
  1.1041 +    /*
  1.1042 +     * wait till the server address is setup
  1.1043 +     */
  1.1044 +    PR_WaitSem(server_sem);
  1.1045 +
  1.1046 +    /*
  1.1047 +     * Now start a bunch of client threads
  1.1048 +     */
  1.1049 +
  1.1050 +    for (i = 0; i < num_udp_clients; i++) {
  1.1051 +        cparamp = PR_NEW(Client_Param);
  1.1052 +        if (cparamp == NULL) {
  1.1053 +            fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1.1054 +            failed_already=1;
  1.1055 +            return -1;
  1.1056 +        }
  1.1057 +        cparamp->server_addr = udp_server_addr;
  1.1058 +        cparamp->exit_mon = mon2;
  1.1059 +        cparamp->exit_counter = &thread_count;
  1.1060 +        cparamp->datalen = datalen;
  1.1061 +        /*
  1.1062 +         * Cause every other client thread to connect udp sockets
  1.1063 +         */
  1.1064 +        cparamp->udp_connect = udp_connect;
  1.1065 +        if (udp_connect)
  1.1066 +            udp_connect = 0;
  1.1067 +        else
  1.1068 +            udp_connect = 1;
  1.1069 +        DPRINTF(("Creating UDP client %d\n", i));
  1.1070 +        t = PR_CreateThread(PR_USER_THREAD,
  1.1071 +            UDP_Client, (void *) cparamp,
  1.1072 +            PR_PRIORITY_NORMAL,
  1.1073 +            PR_LOCAL_THREAD,
  1.1074 +            PR_UNJOINABLE_THREAD,
  1.1075 +            0);
  1.1076 +        if (t == NULL) {
  1.1077 +            fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  1.1078 +            failed_already=1;
  1.1079 +            return -1;
  1.1080 +        }
  1.1081 +        thread_count++;
  1.1082 +    }
  1.1083 +    /* Wait for server and client threads to exit */
  1.1084 +    while (thread_count) {
  1.1085 +        PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
  1.1086 +        DPRINTF(("UDP Server - thread_count  = %d\n", thread_count));
  1.1087 +    }
  1.1088 +    PR_ExitMonitor(mon2);
  1.1089 +    printf("%30s","UDP_Socket_Client_Server_Test: ");
  1.1090 +    printf("%2ld Server %2ld Clients\n",1l, num_udp_clients);
  1.1091 +    printf("%30s %2ld datagrams_per_client %4ld bytes_per_datagram\n",":",
  1.1092 +        num_udp_datagrams_per_client, udp_datagram_size);
  1.1093 +
  1.1094 +    return 0;
  1.1095 +}
  1.1096 +
  1.1097 +static PRFileDesc *small_file_fd, *large_file_fd;
  1.1098 +static void *small_file_addr, *small_file_header, *large_file_addr;
  1.1099 +static void *small_file_trailer, *large_file_header, *large_file_trailer;
  1.1100 +/*
  1.1101 + * TransmitFile_Client
  1.1102 + *    Client Thread
  1.1103 + */
  1.1104 +static void
  1.1105 +TransmitFile_Client(void *arg)
  1.1106 +{
  1.1107 +    PRFileDesc *sockfd;
  1.1108 +    union PRNetAddr netaddr;
  1.1109 +    char *small_buf, *large_buf;
  1.1110 +    Client_Param *cp = (Client_Param *) arg;
  1.1111 +	PRInt32 rlen;
  1.1112 +
  1.1113 +    small_buf = (char*)PR_Malloc(SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
  1.1114 +										SMALL_FILE_TRAILER_SIZE);
  1.1115 +    if (small_buf == NULL) {
  1.1116 +        fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
  1.1117 +        failed_already=1;
  1.1118 +        return;
  1.1119 +    }
  1.1120 +    large_buf = (char*)PR_Malloc(LARGE_FILE_SIZE + LARGE_FILE_HEADER_SIZE +
  1.1121 +												LARGE_FILE_TRAILER_SIZE);
  1.1122 +    if (large_buf == NULL) {
  1.1123 +        fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
  1.1124 +        failed_already=1;
  1.1125 +        return;
  1.1126 +    }
  1.1127 +    netaddr.inet.family = cp->server_addr.inet.family;
  1.1128 +    netaddr.inet.port = cp->server_addr.inet.port;
  1.1129 +    netaddr.inet.ip = cp->server_addr.inet.ip;
  1.1130 +
  1.1131 +    if ((sockfd = PR_NewTCPSocket()) == NULL) {
  1.1132 +        fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
  1.1133 +        failed_already=1;
  1.1134 +        return;
  1.1135 +    }
  1.1136 +
  1.1137 +    if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
  1.1138 +        fprintf(stderr,"prsocket_test: PR_Connect failed\n");
  1.1139 +        failed_already=1;
  1.1140 +        return;
  1.1141 +    }
  1.1142 +    /*
  1.1143 +     * read the small file and verify the data
  1.1144 +     */
  1.1145 +    if (readn(sockfd, small_buf, SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)
  1.1146 +        != (SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)) {
  1.1147 +        fprintf(stderr,
  1.1148 +            "prsocket_test: TransmitFile_Client failed to receive file\n");
  1.1149 +        failed_already=1;
  1.1150 +        return;
  1.1151 +    }
  1.1152 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1153 +    /* File transmission test can not be done because of large file's size */
  1.1154 +    if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1.1155 +        fprintf(stderr,
  1.1156 +            "prsocket_test: TransmitFile_Client ERROR - small file header data corruption\n");
  1.1157 +        failed_already=1;
  1.1158 +        return;
  1.1159 +    }
  1.1160 +    if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
  1.1161 +        SMALL_FILE_SIZE) != 0) {
  1.1162 +        fprintf(stderr,
  1.1163 +            "prsocket_test: TransmitFile_Client ERROR - small file data corruption\n");
  1.1164 +        failed_already=1;
  1.1165 +        return;
  1.1166 +    }
  1.1167 +#endif
  1.1168 +    /*
  1.1169 +     * read the large file and verify the data
  1.1170 +     */
  1.1171 +    if (readn(sockfd, large_buf, LARGE_FILE_SIZE) != LARGE_FILE_SIZE) {
  1.1172 +        fprintf(stderr,
  1.1173 +            "prsocket_test: TransmitFile_Client failed to receive file\n");
  1.1174 +        failed_already=1;
  1.1175 +        return;
  1.1176 +    }
  1.1177 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1178 +    if (memcmp(large_file_addr, large_buf, LARGE_FILE_SIZE) != 0) {
  1.1179 +        fprintf(stderr,
  1.1180 +            "prsocket_test: TransmitFile_Client ERROR - large file data corruption\n");
  1.1181 +        failed_already=1;
  1.1182 +    }
  1.1183 +#endif
  1.1184 +
  1.1185 +
  1.1186 +	/*
  1.1187 +	 * receive data from PR_SendFile
  1.1188 +	 */
  1.1189 +	/*
  1.1190 +	 * case 1: small file with header and trailer
  1.1191 +	 */
  1.1192 +    rlen = SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
  1.1193 +									SMALL_FILE_TRAILER_SIZE;
  1.1194 +    if (readn(sockfd, small_buf, rlen) != rlen) {
  1.1195 +        fprintf(stderr,
  1.1196 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1197 +        failed_already=1;
  1.1198 +        return;
  1.1199 +    }
  1.1200 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1201 +    if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1.1202 +        fprintf(stderr,
  1.1203 +            "SendFile 1. ERROR - small file header corruption\n");
  1.1204 +        failed_already=1;
  1.1205 +        return;
  1.1206 +    }
  1.1207 +    if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
  1.1208 +        								SMALL_FILE_SIZE) != 0) {
  1.1209 +        fprintf(stderr,
  1.1210 +            "SendFile 1. ERROR - small file data corruption\n");
  1.1211 +        failed_already=1;
  1.1212 +        return;
  1.1213 +    }
  1.1214 +    if (memcmp(small_file_trailer,
  1.1215 +				small_buf + SMALL_FILE_HEADER_SIZE + SMALL_FILE_SIZE,
  1.1216 +        				SMALL_FILE_TRAILER_SIZE) != 0) {
  1.1217 +        fprintf(stderr,
  1.1218 +            "SendFile 1. ERROR - small file trailer corruption\n");
  1.1219 +        failed_already=1;
  1.1220 +        return;
  1.1221 +    }
  1.1222 +#endif
  1.1223 +	/*
  1.1224 +	 * case 2: partial large file at zero offset, file with header and trailer
  1.1225 +	 */
  1.1226 +    rlen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
  1.1227 +									LARGE_FILE_TRAILER_SIZE;
  1.1228 +    if (readn(sockfd, large_buf, rlen) != rlen) {
  1.1229 +        fprintf(stderr,
  1.1230 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1231 +        failed_already=1;
  1.1232 +        return;
  1.1233 +    }
  1.1234 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1235 +    if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1.1236 +        fprintf(stderr,
  1.1237 +            "SendFile 2. ERROR - large file header corruption\n");
  1.1238 +        failed_already=1;
  1.1239 +        return;
  1.1240 +    }
  1.1241 +    if (memcmp(large_file_addr, large_buf + LARGE_FILE_HEADER_SIZE,
  1.1242 +        								LARGE_FILE_LEN_1) != 0) {
  1.1243 +        fprintf(stderr,
  1.1244 +            "SendFile 2. ERROR - large file data corruption\n");
  1.1245 +        failed_already=1;
  1.1246 +        return;
  1.1247 +    }
  1.1248 +    if (memcmp(large_file_trailer,
  1.1249 +				large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_1,
  1.1250 +        				LARGE_FILE_TRAILER_SIZE) != 0) {
  1.1251 +        fprintf(stderr,
  1.1252 +            "SendFile 2. ERROR - large file trailer corruption\n");
  1.1253 +        failed_already=1;
  1.1254 +        return;
  1.1255 +    }
  1.1256 +#endif
  1.1257 +	/*
  1.1258 +	 * case 3: partial small file at non-zero offset, with header
  1.1259 +	 */
  1.1260 +    rlen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
  1.1261 +    if (readn(sockfd, small_buf, rlen) != rlen) {
  1.1262 +        fprintf(stderr,
  1.1263 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1264 +        failed_already=1;
  1.1265 +        return;
  1.1266 +    }
  1.1267 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1268 +    if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1.1269 +        fprintf(stderr,
  1.1270 +            "SendFile 3. ERROR - small file header corruption\n");
  1.1271 +        failed_already=1;
  1.1272 +        return;
  1.1273 +    }
  1.1274 +    if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_1,
  1.1275 +				small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_1) != 0) {
  1.1276 +        fprintf(stderr,
  1.1277 +            "SendFile 3. ERROR - small file data corruption\n");
  1.1278 +        failed_already=1;
  1.1279 +        return;
  1.1280 +    }
  1.1281 +#endif
  1.1282 +	/*
  1.1283 +	 * case 4: partial small file at non-zero offset, with trailer
  1.1284 +	 */
  1.1285 +    rlen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
  1.1286 +    if (readn(sockfd, small_buf, rlen) != rlen) {
  1.1287 +        fprintf(stderr,
  1.1288 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1289 +        failed_already=1;
  1.1290 +        return;
  1.1291 +    }
  1.1292 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1293 +    if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_2, small_buf,
  1.1294 +        								SMALL_FILE_LEN_2) != 0) {
  1.1295 +        fprintf(stderr,
  1.1296 +            "SendFile 4. ERROR - small file data corruption\n");
  1.1297 +        failed_already=1;
  1.1298 +        return;
  1.1299 +    }
  1.1300 +    if (memcmp(small_file_trailer, small_buf + SMALL_FILE_LEN_2,
  1.1301 +        				SMALL_FILE_TRAILER_SIZE) != 0) {
  1.1302 +        fprintf(stderr,
  1.1303 +            "SendFile 4. ERROR - small file trailer corruption\n");
  1.1304 +        failed_already=1;
  1.1305 +        return;
  1.1306 +    }
  1.1307 +#endif
  1.1308 +	/*
  1.1309 +	 * case 5: partial large file at non-zero offset, file with header
  1.1310 +	 */
  1.1311 +    rlen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE;
  1.1312 +    if (readn(sockfd, large_buf, rlen) != rlen) {
  1.1313 +        fprintf(stderr,
  1.1314 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1315 +        failed_already=1;
  1.1316 +        return;
  1.1317 +    }
  1.1318 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1319 +    if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1.1320 +        fprintf(stderr,
  1.1321 +            "SendFile 5. ERROR - large file header corruption\n");
  1.1322 +        failed_already=1;
  1.1323 +        return;
  1.1324 +    }
  1.1325 +    if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_2,
  1.1326 +					large_buf + LARGE_FILE_HEADER_SIZE,
  1.1327 +        								LARGE_FILE_LEN_2) != 0) {
  1.1328 +        fprintf(stderr,
  1.1329 +            "SendFile 5. ERROR - large file data corruption\n");
  1.1330 +        failed_already=1;
  1.1331 +        return;
  1.1332 +    }
  1.1333 +#endif
  1.1334 +	/*
  1.1335 +	 * case 6: partial small file at non-zero offset, with header
  1.1336 +	 */
  1.1337 +    rlen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE;
  1.1338 +    if (readn(sockfd, small_buf, rlen) != rlen) {
  1.1339 +        fprintf(stderr,
  1.1340 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1341 +        failed_already=1;
  1.1342 +        return;
  1.1343 +    }
  1.1344 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1345 +    if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1.1346 +        fprintf(stderr,
  1.1347 +            "SendFile 6. ERROR - small file header corruption\n");
  1.1348 +        return;
  1.1349 +    }
  1.1350 +    if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_3,
  1.1351 +				small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_3) != 0) {
  1.1352 +#if 0
  1.1353 +		char *i, *j;
  1.1354 +		int k;
  1.1355 +
  1.1356 +		i = (char *) small_file_addr + SMALL_FILE_OFFSET_3;
  1.1357 +		j = small_buf + SMALL_FILE_HEADER_SIZE;
  1.1358 +		k = SMALL_FILE_LEN_3;
  1.1359 +		while (k-- > 0) {
  1.1360 +			if (*i++ != *j++)
  1.1361 +			printf("i = %d j = %d\n",
  1.1362 +				(int) (i - ((char *) small_file_addr + SMALL_FILE_OFFSET_3)),
  1.1363 +				(int) (j - (small_buf + SMALL_FILE_HEADER_SIZE)));
  1.1364 +		}
  1.1365 +#endif
  1.1366 +        fprintf(stderr,
  1.1367 +            "SendFile 6. ERROR - small file data corruption\n");
  1.1368 +        failed_already=1;
  1.1369 +        return;
  1.1370 +    }
  1.1371 +#endif
  1.1372 +	/*
  1.1373 +	 * case 7: partial large file at non-zero offset, with header
  1.1374 +	 */
  1.1375 +    rlen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE;
  1.1376 +    if (readn(sockfd, large_buf, rlen) != rlen) {
  1.1377 +        fprintf(stderr,
  1.1378 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1379 +        failed_already=1;
  1.1380 +        return;
  1.1381 +    }
  1.1382 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1383 +    if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1.1384 +        fprintf(stderr,
  1.1385 +            "SendFile 7. ERROR - large file header corruption\n");
  1.1386 +        failed_already=1;
  1.1387 +        return;
  1.1388 +    }
  1.1389 +    if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_3,
  1.1390 +					large_buf + LARGE_FILE_HEADER_SIZE,
  1.1391 +        								LARGE_FILE_LEN_3) != 0) {
  1.1392 +        fprintf(stderr,
  1.1393 +            "SendFile 7. ERROR - large file data corruption\n");
  1.1394 +        failed_already=1;
  1.1395 +        return;
  1.1396 +    }
  1.1397 +#endif
  1.1398 +	/*
  1.1399 +	 * case 8: partial large file at non-zero, page-aligned offset, with
  1.1400 +	 * header and trailer
  1.1401 +	 */
  1.1402 +    rlen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE +
  1.1403 +									LARGE_FILE_TRAILER_SIZE;
  1.1404 +    if (readn(sockfd, large_buf, rlen) != rlen) {
  1.1405 +        fprintf(stderr,
  1.1406 +            "prsocket_test: SendFile_Client failed to receive file\n");
  1.1407 +        failed_already=1;
  1.1408 +        return;
  1.1409 +    }
  1.1410 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.1411 +    if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1.1412 +        fprintf(stderr,
  1.1413 +            "SendFile 2. ERROR - large file header corruption\n");
  1.1414 +        failed_already=1;
  1.1415 +        return;
  1.1416 +    }
  1.1417 +    if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_4,
  1.1418 +				large_buf + LARGE_FILE_HEADER_SIZE,
  1.1419 +        								LARGE_FILE_LEN_4) != 0) {
  1.1420 +        fprintf(stderr,
  1.1421 +            "SendFile 2. ERROR - large file data corruption\n");
  1.1422 +        failed_already=1;
  1.1423 +        return;
  1.1424 +    }
  1.1425 +    if (memcmp(large_file_trailer,
  1.1426 +				large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_4,
  1.1427 +        				LARGE_FILE_TRAILER_SIZE) != 0) {
  1.1428 +        fprintf(stderr,
  1.1429 +            "SendFile 2. ERROR - large file trailer corruption\n");
  1.1430 +        failed_already=1;
  1.1431 +        return;
  1.1432 +    }
  1.1433 +#endif
  1.1434 +    PR_DELETE(small_buf);
  1.1435 +    PR_DELETE(large_buf);
  1.1436 +    PR_Close(sockfd);
  1.1437 +
  1.1438 +
  1.1439 +    /*
  1.1440 +     * Decrement exit_counter and notify parent thread
  1.1441 +     */
  1.1442 +
  1.1443 +    PR_EnterMonitor(cp->exit_mon);
  1.1444 +    --(*cp->exit_counter);
  1.1445 +    PR_Notify(cp->exit_mon);
  1.1446 +    PR_ExitMonitor(cp->exit_mon);
  1.1447 +    DPRINTF(("TransmitFile_Client [0x%lx] exiting\n", PR_GetCurrentThread()));
  1.1448 +}
  1.1449 +
  1.1450 +/*
  1.1451 + * Serve_TransmitFile_Client
  1.1452 + *    Thread, started by the server, for serving a client connection.
  1.1453 + *    Trasmits a small file, with a header, and a large file, without
  1.1454 + *    a header
  1.1455 + */
  1.1456 +static void
  1.1457 +Serve_TransmitFile_Client(void *arg)
  1.1458 +{
  1.1459 +    Serve_Client_Param *scp = (Serve_Client_Param *) arg;
  1.1460 +    PRFileDesc *sockfd;
  1.1461 +    PRInt32 bytes;
  1.1462 +    PRFileDesc *local_small_file_fd=NULL;
  1.1463 +    PRFileDesc *local_large_file_fd=NULL;
  1.1464 +	PRSendFileData sfd;
  1.1465 +	PRInt32 slen;
  1.1466 +
  1.1467 +    sockfd = scp->sockfd;
  1.1468 +    local_small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDONLY,0);
  1.1469 +
  1.1470 +    if (local_small_file_fd == NULL) {
  1.1471 +        fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
  1.1472 +            SMALL_FILE_NAME);
  1.1473 +        failed_already=1;
  1.1474 +        goto done;
  1.1475 +    }
  1.1476 +    local_large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDONLY,0);
  1.1477 +
  1.1478 +    if (local_large_file_fd == NULL) {
  1.1479 +        fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
  1.1480 +            LARGE_FILE_NAME);
  1.1481 +        failed_already=1;
  1.1482 +        goto done;
  1.1483 +    }
  1.1484 +    bytes = PR_TransmitFile(sockfd, local_small_file_fd, small_file_header,
  1.1485 +        SMALL_FILE_HEADER_SIZE, PR_TRANSMITFILE_KEEP_OPEN,
  1.1486 +        PR_INTERVAL_NO_TIMEOUT);
  1.1487 +    if (bytes != (SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE)) {
  1.1488 +        fprintf(stderr,
  1.1489 +            "prsocet_test: PR_TransmitFile failed: (%ld, %ld)\n",
  1.1490 +            PR_GetError(), PR_GetOSError());
  1.1491 +        failed_already=1;
  1.1492 +    }
  1.1493 +    bytes = PR_TransmitFile(sockfd, local_large_file_fd, NULL, 0,
  1.1494 +        PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT);
  1.1495 +    if (bytes != LARGE_FILE_SIZE) {
  1.1496 +        fprintf(stderr,
  1.1497 +            "prsocket_test: PR_TransmitFile failed: (%ld, %ld)\n",
  1.1498 +            PR_GetError(), PR_GetOSError());
  1.1499 +        failed_already=1;
  1.1500 +    }
  1.1501 +
  1.1502 +	/*
  1.1503 +	 * PR_SendFile test cases
  1.1504 +	 */
  1.1505 +
  1.1506 +	/*
  1.1507 +	 * case 1: small file with header and trailer
  1.1508 +	 */
  1.1509 +	sfd.fd = local_small_file_fd;
  1.1510 +	sfd.file_offset = 0;
  1.1511 +	sfd.file_nbytes = 0;
  1.1512 +	sfd.header = small_file_header;
  1.1513 +	sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1.1514 +	sfd.trailer = small_file_trailer;
  1.1515 +	sfd.tlen = SMALL_FILE_TRAILER_SIZE;
  1.1516 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1.1517 +        				PR_INTERVAL_NO_TIMEOUT);
  1.1518 +    slen = SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE +
  1.1519 +						SMALL_FILE_TRAILER_SIZE;
  1.1520 +    if (bytes != slen) {
  1.1521 +        fprintf(stderr,
  1.1522 +			"socket: Error - 1. PR_SendFile  send_size = %d, bytes sent = %d\n",
  1.1523 +									slen, bytes);
  1.1524 +        fprintf(stderr,
  1.1525 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1526 +            PR_GetError(), PR_GetOSError());
  1.1527 +        failed_already=1;
  1.1528 +    }
  1.1529 +
  1.1530 +	/*
  1.1531 +	 * case 2: partial large file at zero offset, file with header and trailer
  1.1532 +	 */
  1.1533 +	sfd.fd = local_large_file_fd;
  1.1534 +	sfd.file_offset = 0;
  1.1535 +	sfd.file_nbytes = LARGE_FILE_LEN_1;
  1.1536 +	sfd.header = large_file_header;
  1.1537 +	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1.1538 +	sfd.trailer = large_file_trailer;
  1.1539 +	sfd.tlen = LARGE_FILE_TRAILER_SIZE;
  1.1540 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1.1541 +        				PR_INTERVAL_NO_TIMEOUT);
  1.1542 +    slen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
  1.1543 +						LARGE_FILE_TRAILER_SIZE;
  1.1544 +    if (bytes != slen) {
  1.1545 +        fprintf(stderr,
  1.1546 +			"socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
  1.1547 +									slen, bytes);
  1.1548 +        fprintf(stderr,
  1.1549 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1550 +            PR_GetError(), PR_GetOSError());
  1.1551 +        failed_already=1;
  1.1552 +    }
  1.1553 +	/*
  1.1554 +	 * case 3: partial small file at non-zero offset, with header
  1.1555 +	 */
  1.1556 +	sfd.fd = local_small_file_fd;
  1.1557 +	sfd.file_offset = SMALL_FILE_OFFSET_1;
  1.1558 +	sfd.file_nbytes = SMALL_FILE_LEN_1;
  1.1559 +	sfd.header = small_file_header;
  1.1560 +	sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1.1561 +	sfd.trailer = NULL;
  1.1562 +	sfd.tlen = 0;
  1.1563 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1.1564 +        				PR_INTERVAL_NO_TIMEOUT);
  1.1565 +    slen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
  1.1566 +    if (bytes != slen) {
  1.1567 +        fprintf(stderr,
  1.1568 +			"socket: Error - 3. PR_SendFile send_size = %d, bytes sent = %d\n",
  1.1569 +									slen, bytes);
  1.1570 +        fprintf(stderr,
  1.1571 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1572 +            PR_GetError(), PR_GetOSError());
  1.1573 +        failed_already=1;
  1.1574 +    }
  1.1575 +	/*
  1.1576 +	 * case 4: partial small file at non-zero offset, with trailer
  1.1577 +	 */
  1.1578 +	sfd.fd = local_small_file_fd;
  1.1579 +	sfd.file_offset = SMALL_FILE_OFFSET_2;
  1.1580 +	sfd.file_nbytes = SMALL_FILE_LEN_2;
  1.1581 +	sfd.header = NULL;
  1.1582 +	sfd.hlen = 0;
  1.1583 +	sfd.trailer = small_file_trailer;
  1.1584 +	sfd.tlen = SMALL_FILE_TRAILER_SIZE;
  1.1585 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1.1586 +        				PR_INTERVAL_NO_TIMEOUT);
  1.1587 +    slen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
  1.1588 +    if (bytes != slen) {
  1.1589 +        fprintf(stderr,
  1.1590 +			"socket: Error - 4. PR_SendFile send_size = %d, bytes sent = %d\n",
  1.1591 +									slen, bytes);
  1.1592 +        fprintf(stderr,
  1.1593 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1594 +            PR_GetError(), PR_GetOSError());
  1.1595 +        failed_already=1;
  1.1596 +    }
  1.1597 +	/*
  1.1598 +	 * case 5: partial large file at non-zero offset, file with header
  1.1599 +	 */
  1.1600 +	sfd.fd = local_large_file_fd;
  1.1601 +	sfd.file_offset = LARGE_FILE_OFFSET_2;
  1.1602 +	sfd.file_nbytes = LARGE_FILE_LEN_2;
  1.1603 +	sfd.header = large_file_header;
  1.1604 +	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1.1605 +	sfd.trailer = NULL;
  1.1606 +	sfd.tlen = 0;
  1.1607 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1.1608 +        				PR_INTERVAL_NO_TIMEOUT);
  1.1609 +    slen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE;
  1.1610 +    if (bytes != slen) {
  1.1611 +        fprintf(stderr,
  1.1612 +			"socket: Error - 5. PR_SendFile send_size = %d, bytes sent = %d\n",
  1.1613 +									slen, bytes);
  1.1614 +        fprintf(stderr,
  1.1615 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1616 +            PR_GetError(), PR_GetOSError());
  1.1617 +        failed_already=1;
  1.1618 +    }
  1.1619 +	/*
  1.1620 +	 * case 6: partial small file from non-zero offset till end of file, with header
  1.1621 +	 */
  1.1622 +	sfd.fd = local_small_file_fd;
  1.1623 +	sfd.file_offset = SMALL_FILE_OFFSET_3;
  1.1624 +	sfd.file_nbytes = 0;				/* data from offset to end-of-file */
  1.1625 +	sfd.header = small_file_header;
  1.1626 +	sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1.1627 +	sfd.trailer = NULL;
  1.1628 +	sfd.tlen = 0;
  1.1629 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1.1630 +        				PR_INTERVAL_NO_TIMEOUT);
  1.1631 +    slen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE;
  1.1632 +    if (bytes != slen) {
  1.1633 +        fprintf(stderr,
  1.1634 +			"socket: Error - 6. PR_SendFile send_size = %d, bytes sent = %d\n",
  1.1635 +									slen, bytes);
  1.1636 +        fprintf(stderr,
  1.1637 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1638 +            PR_GetError(), PR_GetOSError());
  1.1639 +        failed_already=1;
  1.1640 +    }
  1.1641 +	/*
  1.1642 +	 * case 7: partial large file at non-zero offset till end-of-file, with header
  1.1643 +	 */
  1.1644 +	sfd.fd = local_large_file_fd;
  1.1645 +	sfd.file_offset = LARGE_FILE_OFFSET_3;
  1.1646 +	sfd.file_nbytes = 0;				/* data until end-of-file */
  1.1647 +	sfd.header = large_file_header;
  1.1648 +	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1.1649 +	sfd.trailer = NULL;
  1.1650 +	sfd.tlen = 0;
  1.1651 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1.1652 +        									PR_INTERVAL_NO_TIMEOUT);
  1.1653 +    slen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE;
  1.1654 +    if (bytes != slen) {
  1.1655 +        fprintf(stderr,
  1.1656 +			"socket: Error - 7. PR_SendFile send_size = %d, bytes sent = %d\n",
  1.1657 +									slen, bytes);
  1.1658 +        fprintf(stderr,
  1.1659 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1660 +            PR_GetError(), PR_GetOSError());
  1.1661 +        failed_already=1;
  1.1662 +    }
  1.1663 +	/*
  1.1664 +	 * case 8: partial large file at non-zero page-aligned offset,
  1.1665 +	 * with header and trailer
  1.1666 +	 */
  1.1667 +	sfd.fd = local_large_file_fd;
  1.1668 +	sfd.file_offset = LARGE_FILE_OFFSET_4;
  1.1669 +	sfd.file_nbytes = LARGE_FILE_LEN_4;
  1.1670 +	sfd.header = large_file_header;
  1.1671 +	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1.1672 +	sfd.trailer = large_file_trailer;
  1.1673 +	sfd.tlen = LARGE_FILE_TRAILER_SIZE;
  1.1674 +    bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_CLOSE_SOCKET,
  1.1675 +        				PR_INTERVAL_NO_TIMEOUT);
  1.1676 +    slen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE +
  1.1677 +						LARGE_FILE_TRAILER_SIZE;
  1.1678 +    if (bytes != slen) {
  1.1679 +        fprintf(stderr,
  1.1680 +			"socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
  1.1681 +									slen, bytes);
  1.1682 +        fprintf(stderr,
  1.1683 +            "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1.1684 +            PR_GetError(), PR_GetOSError());
  1.1685 +        failed_already=1;
  1.1686 +    }
  1.1687 +done:
  1.1688 +    if (local_small_file_fd != NULL)
  1.1689 +        PR_Close(local_small_file_fd);
  1.1690 +    if (local_large_file_fd != NULL)
  1.1691 +        PR_Close(local_large_file_fd);
  1.1692 +}
  1.1693 +
  1.1694 +/*
  1.1695 + * TransmitFile Server
  1.1696 + *    Server Thread
  1.1697 + *    Bind an address to a socket and listen for incoming connections
  1.1698 + *    Create worker threads to service clients
  1.1699 + */
  1.1700 +static void
  1.1701 +TransmitFile_Server(void *arg)
  1.1702 +{
  1.1703 +    PRThread **t = NULL;  /* an array of PRThread pointers */
  1.1704 +    Server_Param *sp = (Server_Param *) arg;
  1.1705 +    Serve_Client_Param *scp;
  1.1706 +    PRFileDesc *sockfd = NULL, *newsockfd;
  1.1707 +    PRNetAddr netaddr;
  1.1708 +    PRInt32 i;
  1.1709 +
  1.1710 +    t = (PRThread**)PR_MALLOC(num_transmitfile_clients * sizeof(PRThread *));
  1.1711 +    if (t == NULL) {
  1.1712 +        fprintf(stderr, "prsocket_test: run out of memory\n");
  1.1713 +        failed_already=1;
  1.1714 +        goto exit;
  1.1715 +    }
  1.1716 +    /*
  1.1717 +     * Create a tcp socket
  1.1718 +     */
  1.1719 +    if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) {
  1.1720 +        fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n");
  1.1721 +        failed_already=1;
  1.1722 +        goto exit;
  1.1723 +    }
  1.1724 +    memset(&netaddr, 0 , sizeof(netaddr));
  1.1725 +    netaddr.inet.family = PR_AF_INET;
  1.1726 +    netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
  1.1727 +    netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
  1.1728 +    /*
  1.1729 +     * try a few times to bind server's address, if addresses are in
  1.1730 +     * use
  1.1731 +     */
  1.1732 +    i = 0;
  1.1733 +    while (PR_Bind(sockfd, &netaddr) < 0) {
  1.1734 +        if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
  1.1735 +            netaddr.inet.port += 2;
  1.1736 +            if (i++ < SERVER_MAX_BIND_COUNT)
  1.1737 +                continue;
  1.1738 +        }
  1.1739 +        fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
  1.1740 +        failed_already=1;
  1.1741 +        perror("PR_Bind");
  1.1742 +        goto exit;
  1.1743 +    }
  1.1744 +
  1.1745 +    if (PR_Listen(sockfd, 32) < 0) {
  1.1746 +        fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n");
  1.1747 +        failed_already=1;
  1.1748 +        goto exit;
  1.1749 +    }
  1.1750 +
  1.1751 +    if (PR_GetSockName(sockfd, &netaddr) < 0) {
  1.1752 +        fprintf(stderr,
  1.1753 +            "prsocket_test: ERROR - PR_GetSockName failed\n");
  1.1754 +        failed_already=1;
  1.1755 +        goto exit;
  1.1756 +    }
  1.1757 +
  1.1758 +    DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
  1.1759 +        netaddr.inet.ip, netaddr.inet.port));
  1.1760 +    tcp_server_addr.inet.family = netaddr.inet.family;
  1.1761 +    tcp_server_addr.inet.port = netaddr.inet.port;
  1.1762 +    tcp_server_addr.inet.ip = netaddr.inet.ip;
  1.1763 +
  1.1764 +    /*
  1.1765 +     * Wake up parent thread because server address is bound and made
  1.1766 +     * available in the global variable 'tcp_server_addr'
  1.1767 +     */
  1.1768 +    PR_PostSem(sp->addr_sem);
  1.1769 +
  1.1770 +    for (i = 0; i < num_transmitfile_clients ; i++) {
  1.1771 +        /* test both null and non-null 'addr' argument to PR_Accept */
  1.1772 +        PRNetAddr *addrp = (i%2 ? &netaddr: NULL);
  1.1773 +
  1.1774 +        if ((newsockfd = PR_Accept(sockfd, addrp,
  1.1775 +            PR_INTERVAL_NO_TIMEOUT)) == NULL) {
  1.1776 +            fprintf(stderr,
  1.1777 +                "prsocket_test: ERROR - PR_Accept failed\n");
  1.1778 +            failed_already=1;
  1.1779 +            goto exit;
  1.1780 +        }
  1.1781 +        /* test both regular and emulated PR_SendFile */
  1.1782 +        if (i%2) {
  1.1783 +            PRFileDesc *layer = PR_CreateIOLayerStub(
  1.1784 +                emuSendFileIdentity, &emuSendFileMethods);
  1.1785 +            if (layer == NULL) {
  1.1786 +                fprintf(stderr,
  1.1787 +                    "prsocket_test: ERROR - PR_CreateIOLayerStub failed\n");
  1.1788 +                failed_already=1;
  1.1789 +                goto exit;
  1.1790 +            }
  1.1791 +            if (PR_PushIOLayer(newsockfd, PR_TOP_IO_LAYER, layer)
  1.1792 +                    == PR_FAILURE) {
  1.1793 +                fprintf(stderr,
  1.1794 +                    "prsocket_test: ERROR - PR_PushIOLayer failed\n");
  1.1795 +                failed_already=1;
  1.1796 +                goto exit;
  1.1797 +            }
  1.1798 +        }
  1.1799 +        scp = PR_NEW(Serve_Client_Param);
  1.1800 +        if (scp == NULL) {
  1.1801 +            fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1.1802 +            failed_already=1;
  1.1803 +            goto exit;
  1.1804 +        }
  1.1805 +
  1.1806 +        /*
  1.1807 +         * Start a Serve_Client thread for each incoming connection
  1.1808 +         */
  1.1809 +        scp->sockfd = newsockfd;
  1.1810 +        scp->datalen = sp->datalen;
  1.1811 +
  1.1812 +        t[i] = PR_CreateThread(PR_USER_THREAD,
  1.1813 +            Serve_TransmitFile_Client, (void *)scp, 
  1.1814 +            PR_PRIORITY_NORMAL,
  1.1815 +            PR_LOCAL_THREAD,
  1.1816 +            PR_JOINABLE_THREAD,
  1.1817 +            0);
  1.1818 +        if (t[i] == NULL) {
  1.1819 +            fprintf(stderr,
  1.1820 +                "prsocket_test: PR_CreateThread failed\n");
  1.1821 +            failed_already=1;
  1.1822 +            goto exit;
  1.1823 +        }
  1.1824 +        DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t));
  1.1825 +    }
  1.1826 +
  1.1827 +    /*
  1.1828 +     * Wait for all the worker threads to end, so that we know
  1.1829 +     * they are no longer using the small and large file fd's.
  1.1830 +     */
  1.1831 +
  1.1832 +    for (i = 0; i < num_transmitfile_clients; i++) {
  1.1833 +        PR_JoinThread(t[i]);
  1.1834 +    }
  1.1835 +
  1.1836 +exit:
  1.1837 +    if (t) {
  1.1838 +        PR_DELETE(t);
  1.1839 +    }
  1.1840 +    if (sockfd) {
  1.1841 +        PR_Close(sockfd);
  1.1842 +    }
  1.1843 +
  1.1844 +    /*
  1.1845 +     * Decrement exit_counter and notify parent thread
  1.1846 +     */
  1.1847 +
  1.1848 +    PR_EnterMonitor(sp->exit_mon);
  1.1849 +    --(*sp->exit_counter);
  1.1850 +    PR_Notify(sp->exit_mon);
  1.1851 +    PR_ExitMonitor(sp->exit_mon);
  1.1852 +    DPRINTF(("TransmitFile_Server [0x%lx] exiting\n", PR_GetCurrentThread()));
  1.1853 +}
  1.1854 +
  1.1855 +/*
  1.1856 + * Socket_Misc_Test    - test miscellaneous functions 
  1.1857 + *    
  1.1858 + */
  1.1859 +static PRInt32
  1.1860 +Socket_Misc_Test(void)
  1.1861 +{
  1.1862 +    PRIntn i, rv = 0, bytes, count, len;
  1.1863 +    PRThread *t;
  1.1864 +    PRSemaphore *server_sem;
  1.1865 +    Server_Param *sparamp;
  1.1866 +    Client_Param *cparamp;
  1.1867 +    PRMonitor *mon2;
  1.1868 +    PRInt32    datalen;
  1.1869 +
  1.1870 +    /*
  1.1871 + * We deliberately pick a buffer size that is not a nice multiple
  1.1872 + * of 1024.
  1.1873 + */
  1.1874 +#define TRANSMITFILE_BUF_SIZE    (4 * 1024 - 11)
  1.1875 +
  1.1876 +    typedef struct {
  1.1877 +        char    data[TRANSMITFILE_BUF_SIZE];
  1.1878 +    } file_buf;
  1.1879 +    file_buf *buf = NULL;
  1.1880 +
  1.1881 +    /*
  1.1882 +     * create file(s) to be transmitted
  1.1883 +     */
  1.1884 +    if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
  1.1885 +        printf("prsocket_test failed to create dir %s\n",TEST_DIR);
  1.1886 +        failed_already=1;
  1.1887 +        return -1;
  1.1888 +    }
  1.1889 +
  1.1890 +    small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777);
  1.1891 +
  1.1892 +    if (small_file_fd == NULL) {
  1.1893 +        fprintf(stderr,"prsocket_test failed to create/open file %s\n",
  1.1894 +            SMALL_FILE_NAME);
  1.1895 +        failed_already=1;
  1.1896 +        rv = -1;
  1.1897 +        goto done;
  1.1898 +    }
  1.1899 +    buf = PR_NEW(file_buf);
  1.1900 +    if (buf == NULL) {
  1.1901 +        fprintf(stderr,"prsocket_test failed to allocate buffer\n");
  1.1902 +        failed_already=1;
  1.1903 +        rv = -1;
  1.1904 +        goto done;
  1.1905 +    }
  1.1906 +    /*
  1.1907 +     * fill in random data
  1.1908 +     */
  1.1909 +    for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
  1.1910 +        buf->data[i] = i;
  1.1911 +    }
  1.1912 +    count = 0;
  1.1913 +    do {
  1.1914 +        len = (SMALL_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ?
  1.1915 +            TRANSMITFILE_BUF_SIZE : (SMALL_FILE_SIZE - count);
  1.1916 +        bytes = PR_Write(small_file_fd, buf->data, len);
  1.1917 +        if (bytes <= 0) {
  1.1918 +            fprintf(stderr,
  1.1919 +                "prsocket_test failed to write to file %s\n",
  1.1920 +                SMALL_FILE_NAME);
  1.1921 +            failed_already=1;
  1.1922 +            rv = -1;
  1.1923 +            goto done;
  1.1924 +        }
  1.1925 +        count += bytes;
  1.1926 +    } while (count < SMALL_FILE_SIZE);
  1.1927 +#ifdef XP_UNIX
  1.1928 +    /*
  1.1929 +     * map the small file; used in checking for data corruption
  1.1930 +     */
  1.1931 +    small_file_addr = mmap(0, SMALL_FILE_SIZE, PROT_READ,
  1.1932 +        MAP_SHARED, small_file_fd->secret->md.osfd, 0);
  1.1933 +    if (small_file_addr == (void *) -1) {
  1.1934 +        fprintf(stderr,"prsocket_test failed to mmap file %s\n",
  1.1935 +            SMALL_FILE_NAME);
  1.1936 +        failed_already=1;
  1.1937 +        rv = -1;
  1.1938 +        goto done;
  1.1939 +    }
  1.1940 +#endif
  1.1941 +    /*
  1.1942 +     * header for small file
  1.1943 +     */
  1.1944 +    small_file_header = PR_MALLOC(SMALL_FILE_HEADER_SIZE);
  1.1945 +    if (small_file_header == NULL) {
  1.1946 +        fprintf(stderr,"prsocket_test failed to malloc header file\n");
  1.1947 +        failed_already=1;
  1.1948 +        rv = -1;
  1.1949 +        goto done;
  1.1950 +    }
  1.1951 +    memset(small_file_header, (int) PR_IntervalNow(),
  1.1952 +        SMALL_FILE_HEADER_SIZE);
  1.1953 +    /*
  1.1954 +     * trailer for small file
  1.1955 +     */
  1.1956 +    small_file_trailer = PR_MALLOC(SMALL_FILE_TRAILER_SIZE);
  1.1957 +    if (small_file_trailer == NULL) {
  1.1958 +        fprintf(stderr,"prsocket_test failed to malloc header trailer\n");
  1.1959 +        failed_already=1;
  1.1960 +        rv = -1;
  1.1961 +        goto done;
  1.1962 +    }
  1.1963 +    memset(small_file_trailer, (int) PR_IntervalNow(),
  1.1964 +        SMALL_FILE_TRAILER_SIZE);
  1.1965 +    /*
  1.1966 +     * setup large file
  1.1967 +     */
  1.1968 +    large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777);
  1.1969 +
  1.1970 +    if (large_file_fd == NULL) {
  1.1971 +        fprintf(stderr,"prsocket_test failed to create/open file %s\n",
  1.1972 +            LARGE_FILE_NAME);
  1.1973 +        failed_already=1;
  1.1974 +        rv = -1;
  1.1975 +        goto done;
  1.1976 +    }
  1.1977 +    /*
  1.1978 +     * fill in random data
  1.1979 +     */
  1.1980 +    for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
  1.1981 +        buf->data[i] = i;
  1.1982 +    }
  1.1983 +    count = 0;
  1.1984 +    do {
  1.1985 +        len = (LARGE_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ?
  1.1986 +            TRANSMITFILE_BUF_SIZE : (LARGE_FILE_SIZE - count);
  1.1987 +        bytes = PR_Write(large_file_fd, buf->data, len);
  1.1988 +        if (bytes <= 0) {
  1.1989 +            fprintf(stderr,
  1.1990 +                "prsocket_test failed to write to file %s: (%ld, %ld)\n",
  1.1991 +                LARGE_FILE_NAME,
  1.1992 +                PR_GetError(), PR_GetOSError());
  1.1993 +            failed_already=1;
  1.1994 +            rv = -1;
  1.1995 +            goto done;
  1.1996 +        }
  1.1997 +        count += bytes;
  1.1998 +    } while (count < LARGE_FILE_SIZE);
  1.1999 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.2000 +    /*
  1.2001 +     * map the large file; used in checking for data corruption
  1.2002 +     */
  1.2003 +    large_file_addr = mmap(0, LARGE_FILE_SIZE, PROT_READ,
  1.2004 +        MAP_SHARED, large_file_fd->secret->md.osfd, 0);
  1.2005 +    if (large_file_addr == (void *) -1) {
  1.2006 +        fprintf(stderr,"prsocket_test failed to mmap file %s\n",
  1.2007 +            LARGE_FILE_NAME);
  1.2008 +        failed_already=1;
  1.2009 +        rv = -1;
  1.2010 +        goto done;
  1.2011 +    }
  1.2012 +#endif
  1.2013 +    /*
  1.2014 +     * header for large file
  1.2015 +     */
  1.2016 +    large_file_header = PR_MALLOC(LARGE_FILE_HEADER_SIZE);
  1.2017 +    if (large_file_header == NULL) {
  1.2018 +        fprintf(stderr,"prsocket_test failed to malloc header file\n");
  1.2019 +        failed_already=1;
  1.2020 +        rv = -1;
  1.2021 +        goto done;
  1.2022 +    }
  1.2023 +    memset(large_file_header, (int) PR_IntervalNow(),
  1.2024 +        LARGE_FILE_HEADER_SIZE);
  1.2025 +    /*
  1.2026 +     * trailer for large file
  1.2027 +     */
  1.2028 +    large_file_trailer = PR_MALLOC(LARGE_FILE_TRAILER_SIZE);
  1.2029 +    if (large_file_trailer == NULL) {
  1.2030 +        fprintf(stderr,"prsocket_test failed to malloc header trailer\n");
  1.2031 +        failed_already=1;
  1.2032 +        rv = -1;
  1.2033 +        goto done;
  1.2034 +    }
  1.2035 +    memset(large_file_trailer, (int) PR_IntervalNow(),
  1.2036 +        LARGE_FILE_TRAILER_SIZE);
  1.2037 +
  1.2038 +    datalen = tcp_mesg_size;
  1.2039 +    thread_count = 0;
  1.2040 +    /*
  1.2041 +     * start the server thread
  1.2042 +     */
  1.2043 +    sparamp = PR_NEW(Server_Param);
  1.2044 +    if (sparamp == NULL) {
  1.2045 +        fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1.2046 +        failed_already=1;
  1.2047 +        rv = -1;
  1.2048 +        goto done;
  1.2049 +    }
  1.2050 +    server_sem = PR_NewSem(0);
  1.2051 +    if (server_sem == NULL) {
  1.2052 +        fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
  1.2053 +        failed_already=1;
  1.2054 +        rv = -1;
  1.2055 +        goto done;
  1.2056 +    }
  1.2057 +    mon2 = PR_NewMonitor();
  1.2058 +    if (mon2 == NULL) {
  1.2059 +        fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
  1.2060 +        failed_already=1;
  1.2061 +        rv = -1;
  1.2062 +        goto done;
  1.2063 +    }
  1.2064 +    PR_EnterMonitor(mon2);
  1.2065 +
  1.2066 +    sparamp->addr_sem = server_sem;
  1.2067 +    sparamp->exit_mon = mon2;
  1.2068 +    sparamp->exit_counter = &thread_count;
  1.2069 +    sparamp->datalen = datalen;
  1.2070 +    t = PR_CreateThread(PR_USER_THREAD,
  1.2071 +        TransmitFile_Server, (void *)sparamp, 
  1.2072 +        PR_PRIORITY_NORMAL,
  1.2073 +        PR_LOCAL_THREAD,
  1.2074 +        PR_UNJOINABLE_THREAD,
  1.2075 +        0);
  1.2076 +    if (t == NULL) {
  1.2077 +        fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  1.2078 +        failed_already=1;
  1.2079 +        rv = -1;
  1.2080 +        goto done;
  1.2081 +    }
  1.2082 +    DPRINTF(("Created TCP server = 0x%x\n", t));
  1.2083 +    thread_count++;
  1.2084 +
  1.2085 +    /*
  1.2086 +     * wait till the server address is setup
  1.2087 +     */
  1.2088 +    PR_WaitSem(server_sem);
  1.2089 +
  1.2090 +    /*
  1.2091 +     * Now start a bunch of client threads
  1.2092 +     */
  1.2093 +
  1.2094 +    cparamp = PR_NEW(Client_Param);
  1.2095 +    if (cparamp == NULL) {
  1.2096 +        fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1.2097 +        failed_already=1;
  1.2098 +        rv = -1;
  1.2099 +        goto done;
  1.2100 +    }
  1.2101 +    cparamp->server_addr = tcp_server_addr;
  1.2102 +    cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
  1.2103 +    cparamp->exit_mon = mon2;
  1.2104 +    cparamp->exit_counter = &thread_count;
  1.2105 +    cparamp->datalen = datalen;
  1.2106 +    for (i = 0; i < num_transmitfile_clients; i++) {
  1.2107 +        t = create_new_thread(PR_USER_THREAD,
  1.2108 +            TransmitFile_Client, (void *) cparamp,
  1.2109 +            PR_PRIORITY_NORMAL,
  1.2110 +            PR_LOCAL_THREAD,
  1.2111 +            PR_UNJOINABLE_THREAD,
  1.2112 +            0, i);
  1.2113 +        if (t == NULL) {
  1.2114 +            fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  1.2115 +            rv = -1;
  1.2116 +            failed_already=1;
  1.2117 +            goto done;
  1.2118 +        }
  1.2119 +        DPRINTF(("Created TransmitFile client = 0x%lx\n", t));
  1.2120 +        thread_count++;
  1.2121 +    }
  1.2122 +    /* Wait for server and client threads to exit */
  1.2123 +    while (thread_count) {
  1.2124 +        PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
  1.2125 +        DPRINTF(("Socket_Misc_Test - thread_count  = %d\n", thread_count));
  1.2126 +    }
  1.2127 +    PR_ExitMonitor(mon2);
  1.2128 +done:
  1.2129 +    if (buf) {
  1.2130 +        PR_DELETE(buf);
  1.2131 +    }
  1.2132 +#if defined(XP_UNIX) && !defined(SYMBIAN)
  1.2133 +    munmap((char*)small_file_addr, SMALL_FILE_SIZE);
  1.2134 +    munmap((char*)large_file_addr, LARGE_FILE_SIZE);
  1.2135 +#endif
  1.2136 +    PR_Close(small_file_fd);
  1.2137 +    PR_Close(large_file_fd);
  1.2138 +    if ((PR_Delete(SMALL_FILE_NAME)) == PR_FAILURE) {
  1.2139 +        fprintf(stderr,"prsocket_test: failed to unlink file %s\n",
  1.2140 +            SMALL_FILE_NAME);
  1.2141 +        failed_already=1;
  1.2142 +    }
  1.2143 +    if ((PR_Delete(LARGE_FILE_NAME)) == PR_FAILURE) {
  1.2144 +        fprintf(stderr,"prsocket_test: failed to unlink file %s\n",
  1.2145 +            LARGE_FILE_NAME);
  1.2146 +        failed_already=1;
  1.2147 +    }
  1.2148 +    if ((PR_RmDir(TEST_DIR)) == PR_FAILURE) {
  1.2149 +        fprintf(stderr,"prsocket_test failed to rmdir %s: (%ld, %ld)\n",
  1.2150 +            TEST_DIR, PR_GetError(), PR_GetOSError());
  1.2151 +        failed_already=1;
  1.2152 +    }
  1.2153 +
  1.2154 +    printf("%-29s%s","Socket_Misc_Test",":");
  1.2155 +    printf("%2d Server %2d Clients\n",1, num_transmitfile_clients);
  1.2156 +    printf("%30s Sizes of Transmitted Files  - %4d KB, %2d MB \n",":",
  1.2157 +        SMALL_FILE_SIZE/1024, LARGE_FILE_SIZE/(1024 * 1024));
  1.2158 +
  1.2159 +
  1.2160 +    return rv;
  1.2161 +}
  1.2162 +/************************************************************************/
  1.2163 +
  1.2164 +/*
  1.2165 + * Test Socket NSPR APIs
  1.2166 + */
  1.2167 +
  1.2168 +int main(int argc, char **argv)
  1.2169 +{
  1.2170 +    /*
  1.2171 +     * -d           debug mode
  1.2172 +     */
  1.2173 +
  1.2174 +    PLOptStatus os;
  1.2175 +    PLOptState *opt = PL_CreateOptState(argc, argv, "d");
  1.2176 +    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  1.2177 +    {
  1.2178 +        if (PL_OPT_BAD == os) continue;
  1.2179 +        switch (opt->option)
  1.2180 +        {
  1.2181 +        case 'd':  /* debug mode */
  1.2182 +            _debug_on = 1;
  1.2183 +            break;
  1.2184 +        default:
  1.2185 +            break;
  1.2186 +        }
  1.2187 +    }
  1.2188 +    PL_DestroyOptState(opt);
  1.2189 +
  1.2190 +    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  1.2191 +    PR_STDIO_INIT();
  1.2192 +
  1.2193 +    PR_SetConcurrency(4);
  1.2194 +
  1.2195 +    emuSendFileIdentity = PR_GetUniqueIdentity("Emulated SendFile");
  1.2196 +    emuSendFileMethods = *PR_GetDefaultIOMethods();
  1.2197 +    emuSendFileMethods.transmitfile = emu_TransmitFile;
  1.2198 +    emuSendFileMethods.sendfile = emu_SendFile;
  1.2199 +
  1.2200 +    /*
  1.2201 +     * run client-server test with TCP, Ipv4-Ipv4
  1.2202 +     */
  1.2203 +	printf("TCP Client/Server Test - IPv4/Ipv4\n");
  1.2204 +    if (TCP_Socket_Client_Server_Test() < 0) {
  1.2205 +        printf("TCP_Socket_Client_Server_Test failed\n");
  1.2206 +        goto done;
  1.2207 +    } else
  1.2208 +        printf("TCP_Socket_Client_Server_Test Passed\n");
  1.2209 +    /*
  1.2210 +     * client-server test, Ipv6-Ipv4
  1.2211 +     */
  1.2212 +	client_domain = PR_AF_INET6;
  1.2213 +	printf("TCP Client/Server Test - IPv6/Ipv4\n");
  1.2214 +    if (TCP_Socket_Client_Server_Test() < 0) {
  1.2215 +        printf("TCP_Socket_Client_Server_Test failed\n");
  1.2216 +        goto done;
  1.2217 +    } else
  1.2218 +        printf("TCP_Socket_Client_Server_Test Passed\n");
  1.2219 +    /*
  1.2220 +     * client-server test, Ipv4-Ipv6
  1.2221 +     */
  1.2222 +	client_domain = PR_AF_INET;
  1.2223 +	server_domain = PR_AF_INET6;
  1.2224 +	printf("TCP Client/Server Test - IPv4/Ipv6\n");
  1.2225 +    if (TCP_Socket_Client_Server_Test() < 0) {
  1.2226 +        printf("TCP_Socket_Client_Server_Test failed\n");
  1.2227 +        goto done;
  1.2228 +    } else
  1.2229 +        printf("TCP_Socket_Client_Server_Test Passed\n");
  1.2230 +    /*
  1.2231 +     * client-server test, Ipv6-Ipv6
  1.2232 +     */
  1.2233 +	client_domain = PR_AF_INET6;
  1.2234 +	server_domain = PR_AF_INET6;
  1.2235 +	printf("TCP Client/Server Test - IPv6/Ipv6\n");
  1.2236 +    if (TCP_Socket_Client_Server_Test() < 0) {
  1.2237 +        printf("TCP_Socket_Client_Server_Test failed\n");
  1.2238 +        goto done;
  1.2239 +    } else
  1.2240 +        printf("TCP_Socket_Client_Server_Test Passed\n");
  1.2241 +	test_cancelio = 0;
  1.2242 +	
  1.2243 +#if defined(SYMBIAN) && !defined(__WINSCW__)
  1.2244 +	/* UDP tests only run on Symbian devices but not emulator */
  1.2245 +    /*
  1.2246 +     * run client-server test with UDP, IPv4/IPv4
  1.2247 +     */
  1.2248 +	printf("UDP Client/Server Test - IPv4/Ipv4\n");
  1.2249 +	client_domain = PR_AF_INET;
  1.2250 +	server_domain = PR_AF_INET;
  1.2251 +    if (UDP_Socket_Client_Server_Test() < 0) {
  1.2252 +        printf("UDP_Socket_Client_Server_Test failed\n");
  1.2253 +        goto done;
  1.2254 +    } else
  1.2255 +        printf("UDP_Socket_Client_Server_Test Passed\n");
  1.2256 +    /*
  1.2257 +     * run client-server test with UDP, IPv6/IPv4
  1.2258 +     */
  1.2259 +	printf("UDP Client/Server Test - IPv6/Ipv4\n");
  1.2260 +	client_domain = PR_AF_INET6;
  1.2261 +	server_domain = PR_AF_INET;
  1.2262 +    if (UDP_Socket_Client_Server_Test() < 0) {
  1.2263 +        printf("UDP_Socket_Client_Server_Test failed\n");
  1.2264 +        goto done;
  1.2265 +    } else
  1.2266 +        printf("UDP_Socket_Client_Server_Test Passed\n");
  1.2267 +    /*
  1.2268 +     * run client-server test with UDP,IPv4-IPv6
  1.2269 +     */
  1.2270 +	printf("UDP Client/Server Test - IPv4/Ipv6\n");
  1.2271 +	client_domain = PR_AF_INET;
  1.2272 +	server_domain = PR_AF_INET6;
  1.2273 +    if (UDP_Socket_Client_Server_Test() < 0) {
  1.2274 +        printf("UDP_Socket_Client_Server_Test failed\n");
  1.2275 +        goto done;
  1.2276 +    } else
  1.2277 +        printf("UDP_Socket_Client_Server_Test Passed\n");
  1.2278 +    /*
  1.2279 +     * run client-server test with UDP,IPv6-IPv6
  1.2280 +     */
  1.2281 +	printf("UDP Client/Server Test - IPv6/Ipv6\n");
  1.2282 +	client_domain = PR_AF_INET6;
  1.2283 +	server_domain = PR_AF_INET6;
  1.2284 +    if (UDP_Socket_Client_Server_Test() < 0) {
  1.2285 +        printf("UDP_Socket_Client_Server_Test failed\n");
  1.2286 +        goto done;
  1.2287 +    } else
  1.2288 +        printf("UDP_Socket_Client_Server_Test Passed\n");
  1.2289 +#endif
  1.2290 +    
  1.2291 +    /*
  1.2292 +     * Misc socket tests - including transmitfile, etc.
  1.2293 +     */
  1.2294 +
  1.2295 +    /* File transmission test can not be done in Symbian OS because of 
  1.2296 +     * large file's size and the incomplete mmap() implementation. */
  1.2297 +#if !defined(WIN16) && !defined(SYMBIAN)
  1.2298 +    /*
  1.2299 +** The 'transmit file' test does not run because
  1.2300 +** transmit file is not implemented in NSPR yet.
  1.2301 +**
  1.2302 +*/
  1.2303 +    if (Socket_Misc_Test() < 0) {
  1.2304 +        printf("Socket_Misc_Test failed\n");
  1.2305 +        failed_already=1;
  1.2306 +        goto done;
  1.2307 +    } else
  1.2308 +        printf("Socket_Misc_Test passed\n");
  1.2309 +
  1.2310 +    /*
  1.2311 +     * run client-server test with TCP again to test
  1.2312 +     * recycling used sockets from PR_TransmitFile().
  1.2313 +     */
  1.2314 +    if (TCP_Socket_Client_Server_Test() < 0) {
  1.2315 +        printf("TCP_Socket_Client_Server_Test failed\n");
  1.2316 +        goto done;
  1.2317 +    } else
  1.2318 +        printf("TCP_Socket_Client_Server_Test Passed\n");
  1.2319 +#endif
  1.2320 +
  1.2321 +done:
  1.2322 +    PR_Cleanup();
  1.2323 +    if (failed_already) return 1;
  1.2324 +    else return 0;
  1.2325 +}

mercurial