nsprpub/pr/tests/socket.c

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /***********************************************************************
     7 **
     8 ** Name: socket.c
     9 **
    10 ** Description: Test socket functionality.
    11 **
    12 ** Modification History:
    13 */
    14 #include "primpl.h"
    16 #include "plgetopt.h"
    18 #include <stdio.h>
    19 #include <string.h>
    20 #include <errno.h>
    21 #ifdef XP_UNIX
    22 #include <sys/mman.h>
    23 #endif
    24 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
    25 #include <pthread.h>
    26 #endif
    28 #ifdef WIN32
    29 #include <process.h>
    30 #endif
    32 static int _debug_on = 0;
    33 static int test_cancelio = 0;
    35 #include "obsolete/prsem.h"
    37 #ifdef XP_PC
    38 #define mode_t int
    39 #endif
    41 #define DPRINTF(arg) if (_debug_on) printf arg
    43 #ifdef XP_PC
    44 char *TEST_DIR = "prdir";
    45 char *SMALL_FILE_NAME = "prsmallf";
    46 char *LARGE_FILE_NAME = "prlargef";
    47 #elif defined(SYMBIAN)
    48 char *TEST_DIR = "c:\\data\\prsocket";
    49 char *SMALL_FILE_NAME = "c:\\data\\prsocket\\small_file";
    50 char *LARGE_FILE_NAME = "c:\\data\\prsocket\\large_file";
    51 #else
    52 char *TEST_DIR = "/tmp/prsocket_test_dir";
    53 char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file";
    54 char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file";
    55 #endif
    56 #define SMALL_FILE_SIZE				(3 * 1024)        /* 3 KB        */
    57 #define SMALL_FILE_OFFSET_1			(512)
    58 #define SMALL_FILE_LEN_1			(1 * 1024)        /* 1 KB        */
    59 #define SMALL_FILE_OFFSET_2			(75)
    60 #define SMALL_FILE_LEN_2			(758)
    61 #define SMALL_FILE_OFFSET_3			(1024)
    62 #define SMALL_FILE_LEN_3			(SMALL_FILE_SIZE - SMALL_FILE_OFFSET_3)
    63 #define SMALL_FILE_HEADER_SIZE    	(64)            /* 64 bytes    */
    64 #define SMALL_FILE_TRAILER_SIZE   	(128)           /* 128 bytes    */
    66 #define LARGE_FILE_SIZE				(3 * 1024 * 1024)    /* 3 MB        */
    67 #define LARGE_FILE_OFFSET_1			(0)
    68 #define LARGE_FILE_LEN_1			(2 * 1024 * 1024)    /* 2 MB        */
    69 #define LARGE_FILE_OFFSET_2			(64)
    70 #define LARGE_FILE_LEN_2			(1 * 1024 * 1024 + 75)
    71 #define LARGE_FILE_OFFSET_3			(2 * 1024 * 1024 - 128)
    72 #define LARGE_FILE_LEN_3			(LARGE_FILE_SIZE - LARGE_FILE_OFFSET_3)
    73 #define LARGE_FILE_OFFSET_4			PR_GetPageSize()
    74 #define LARGE_FILE_LEN_4			769
    75 #define LARGE_FILE_HEADER_SIZE    	(512)
    76 #define LARGE_FILE_TRAILER_SIZE   	(64)
    78 #define    BUF_DATA_SIZE    (2 * 1024)
    79 #define TCP_MESG_SIZE    1024
    80 /*
    81  * set UDP datagram size small enough that datagrams sent to a port on the
    82  * local host will not be lost
    83  */
    84 #define UDP_DGRAM_SIZE            128
    85 #define NUM_TCP_CLIENTS            5	/* for a listen queue depth of 5 */
    86 #define NUM_UDP_CLIENTS            10
    88 #ifdef SYMBIAN
    89 #define NUM_TRANSMITFILE_CLIENTS    1
    90 #else
    91 #define NUM_TRANSMITFILE_CLIENTS    4
    92 #endif
    94 #define NUM_TCP_CONNECTIONS_PER_CLIENT    5
    95 #define NUM_TCP_MESGS_PER_CONNECTION    10
    96 #define NUM_UDP_DATAGRAMS_PER_CLIENT    5
    97 #define TCP_SERVER_PORT            10000
    98 #define UDP_SERVER_PORT            TCP_SERVER_PORT
    99 #define SERVER_MAX_BIND_COUNT        100
   101 #ifdef WINCE
   102 #define perror(s)
   103 #endif
   105 static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
   106 static PRInt32 num_udp_clients = NUM_UDP_CLIENTS;
   107 static PRInt32 num_transmitfile_clients = NUM_TRANSMITFILE_CLIENTS;
   108 static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
   109 static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
   110 static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
   111 static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT;
   112 static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE;
   114 static PRInt32 thread_count;
   115 PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET;
   117 /* an I/O layer that uses the emulated senfile method */
   118 static PRDescIdentity emuSendFileIdentity;
   119 static PRIOMethods emuSendFileMethods;
   121 int failed_already=0;
   122 typedef struct buffer {
   123     char    data[BUF_DATA_SIZE];
   124 } buffer;
   126 PRNetAddr tcp_server_addr, udp_server_addr;
   128 typedef struct Serve_Client_Param {
   129     PRFileDesc *sockfd;    /* socket to read from/write to    */
   130     PRInt32    datalen;    /* bytes of data transfered in each read/write */
   131 } Serve_Client_Param;
   133 typedef struct Server_Param {
   134     PRSemaphore *addr_sem;    /* sem to post on, after setting up the address */
   135     PRMonitor *exit_mon;    /* monitor to signal on exit            */
   136     PRInt32 *exit_counter;    /* counter to decrement, before exit        */
   137     PRInt32    datalen;    /* bytes of data transfered in each read/write    */
   138 } Server_Param;
   141 typedef struct Client_Param {
   142     PRNetAddr server_addr;
   143     PRMonitor *exit_mon;    /* monitor to signal on exit */
   144     PRInt32 *exit_counter;    /* counter to decrement, before exit */
   145     PRInt32    datalen;
   146     PRInt32    udp_connect;    /* if set clients connect udp sockets */
   147 } Client_Param;
   149 /* the sendfile method in emuSendFileMethods */
   150 static PRInt32 PR_CALLBACK
   151 emu_SendFile(PRFileDesc *sd, PRSendFileData *sfd,
   152     PRTransmitFileFlags flags, PRIntervalTime timeout)
   153 {
   154     return PR_EmulateSendFile(sd, sfd, flags, timeout);
   155 }
   157 /* the transmitfile method in emuSendFileMethods */
   158 static PRInt32 PR_CALLBACK
   159 emu_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers,
   160     PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
   161 {
   162     PRSendFileData sfd;
   164     sfd.fd = fd;
   165     sfd.file_offset = 0;
   166     sfd.file_nbytes = 0;
   167     sfd.header = headers;
   168     sfd.hlen = hlen;
   169     sfd.trailer = NULL;
   170     sfd.tlen = 0;
   171     return emu_SendFile(sd, &sfd, flags, timeout);
   172 }
   174 /*
   175  * readn
   176  *    read data from sockfd into buf
   177  */
   178 static PRInt32
   179 readn(PRFileDesc *sockfd, char *buf, int len)
   180 {
   181     int rem;
   182     int bytes;
   183     int offset = 0;
   184 	int err;
   185 	PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
   187 	if (test_cancelio)
   188 		timeout = PR_SecondsToInterval(2);
   190     for (rem=len; rem; offset += bytes, rem -= bytes) {
   191         DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",
   192             PR_GetCurrentThread(), rem));
   193 retry:
   194         bytes = PR_Recv(sockfd, buf + offset, rem, 0,
   195             	timeout);
   196         DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",
   197             PR_GetCurrentThread(), bytes));
   198         if (bytes < 0) {
   199 #ifdef WINNT
   200 			printf("PR_Recv: error = %d oserr = %d\n",(err = PR_GetError()),
   201 									PR_GetOSError());
   202 			if ((test_cancelio) && (err == PR_IO_TIMEOUT_ERROR)) {
   203 				if (PR_NT_CancelIo(sockfd) != PR_SUCCESS)
   204 					printf("PR_NT_CancelIO: error = %d\n",PR_GetError());
   205 				timeout = PR_INTERVAL_NO_TIMEOUT;
   206 				goto retry;
   207 			}
   208 #endif
   209 			return -1;
   210 		}	
   211     }
   212     return len;
   213 }
   215 /*
   216  * writen
   217  *    write data from buf to sockfd
   218  */
   219 static PRInt32
   220 writen(PRFileDesc *sockfd, char *buf, int len)
   221 {
   222     int rem;
   223     int bytes;
   224     int offset = 0;
   226     for (rem=len; rem; offset += bytes, rem -= bytes) {
   227         DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
   228             PR_GetCurrentThread(), rem));
   229         bytes = PR_Send(sockfd, buf + offset, rem, 0,
   230             PR_INTERVAL_NO_TIMEOUT);
   231         DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
   232             PR_GetCurrentThread(), bytes));
   233         if (bytes <= 0)
   234             return -1;
   235     }
   236     return len;
   237 }
   239 /*
   240  * Serve_Client
   241  *    Thread, started by the server, for serving a client connection.
   242  *    Reads data from socket and writes it back, unmodified, and
   243  *    closes the socket
   244  */
   245 static void PR_CALLBACK
   246 Serve_Client(void *arg)
   247 {
   248     Serve_Client_Param *scp = (Serve_Client_Param *) arg;
   249     PRFileDesc *sockfd;
   250     buffer *in_buf;
   251     PRInt32 bytes, j;
   253     sockfd = scp->sockfd;
   254     bytes = scp->datalen;
   255     in_buf = PR_NEW(buffer);
   256     if (in_buf == NULL) {
   257         fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   258         failed_already=1;
   259         goto exit;
   260     }
   263     for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
   264         /*
   265          * Read data from client and send it back to the client unmodified
   266          */
   267         if (readn(sockfd, in_buf->data, bytes) < bytes) {
   268             fprintf(stderr,"prsocket_test: ERROR - Serve_Client:readn\n");
   269             failed_already=1;
   270             goto exit;
   271         }
   272         /* Shutdown only RCV will cause error on Symbian OS */
   273 #if !defined(SYMBIAN)
   274         /*
   275          * shutdown reads, after the last read
   276          */
   277         if (j == num_tcp_mesgs_per_connection - 1)
   278             if (PR_Shutdown(sockfd, PR_SHUTDOWN_RCV) < 0) {
   279                 fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
   280             }
   281 #endif
   282         DPRINTF(("Serve_Client [0x%lx]: inbuf[0] = 0x%lx\n",PR_GetCurrentThread(),
   283             (*((int *) in_buf->data))));
   284         if (writen(sockfd, in_buf->data, bytes) < bytes) {
   285             fprintf(stderr,"prsocket_test: ERROR - Serve_Client:writen\n");
   286             failed_already=1;
   287             goto exit;
   288         }
   289     }
   290     /*
   291      * shutdown reads and writes
   292      */
   293     if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
   294         fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
   295         failed_already=1;
   296     }
   298 exit:
   299     PR_Close(sockfd);
   300     if (in_buf) {
   301         PR_DELETE(in_buf);
   302     }
   303 }
   305 PRThread* create_new_thread(PRThreadType type,
   306 							void (*start)(void *arg),
   307 							void *arg,
   308 							PRThreadPriority priority,
   309 							PRThreadScope scope,
   310 							PRThreadState state,
   311 							PRUint32 stackSize, PRInt32 index)
   312 {
   313 PRInt32 native_thread = 0;
   315 	PR_ASSERT(state == PR_UNJOINABLE_THREAD);
   316 #if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32)
   317 	switch(index %  4) {
   318 		case 0:
   319 			scope = (PR_LOCAL_THREAD);
   320 			break;
   321 		case 1:
   322 			scope = (PR_GLOBAL_THREAD);
   323 			break;
   324 		case 2:
   325 			scope = (PR_GLOBAL_BOUND_THREAD);
   326 			break;
   327 		case 3:
   328 			native_thread = 1;
   329 			break;
   330 		default:
   331 			PR_ASSERT(!"Invalid scope");
   332 			break;
   333 	}
   334 	if (native_thread) {
   335 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
   336 		pthread_t tid;
   337 		if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg))
   338 			return((PRThread *) tid);
   339 		else
   340 			return (NULL);
   341 #else
   342 		HANDLE thandle;
   343 		unsigned tid;
   345 		thandle = (HANDLE) _beginthreadex(
   346 						NULL,
   347 						stackSize,
   348 						(unsigned (__stdcall *)(void *))start,
   349 						arg,
   350 						STACK_SIZE_PARAM_IS_A_RESERVATION,
   351 						&tid);		
   352 		return((PRThread *) thandle);
   353 #endif
   354 	} else {
   355 		return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
   356 	}
   357 #else
   358 	return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
   359 #endif
   360 }
   362 /*
   363  * TCP Server
   364  *    Server Thread
   365  *    Bind an address to a socket and listen for incoming connections
   366  *    Start a Serve_Client thread for each incoming connection.
   367  */
   368 static void PR_CALLBACK
   369 TCP_Server(void *arg)
   370 {
   371     PRThread *t;
   372     Server_Param *sp = (Server_Param *) arg;
   373     Serve_Client_Param *scp;
   374     PRFileDesc *sockfd, *newsockfd;
   375     PRNetAddr netaddr;
   376     PRInt32 i;
   377     /*
   378      * Create a tcp socket
   379      */
   380 	if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) {
   381         fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
   382         goto exit;
   383     }
   384     memset(&netaddr, 0 , sizeof(netaddr));
   386 	if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT,
   387 									&netaddr) == PR_FAILURE) {
   388         fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   389         goto exit;
   390 	}
   391     /*
   392      * try a few times to bind server's address, if addresses are in
   393      * use
   394      */
   395     i = 0;
   397     while (PR_Bind(sockfd, &netaddr) < 0) {
   398         if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
   399             netaddr.inet.port += 2;
   400             if (i++ < SERVER_MAX_BIND_COUNT)
   401                 continue;
   402         }
   403         fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
   404         perror("PR_Bind");
   405         failed_already=1;
   406         goto exit;
   407     }
   409     if (PR_Listen(sockfd, 32) < 0) {
   410         fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n");
   411         failed_already=1;
   412         goto exit;
   413     }
   415     if (PR_GetSockName(sockfd, &netaddr) < 0) {
   416         fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
   417         failed_already=1;
   418         goto exit;
   419     }
   421     DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
   422         netaddr.inet.ip, netaddr.inet.port));
   423 	if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
   424 									PR_ntohs(PR_NetAddrInetPort(&netaddr)),
   425 									&tcp_server_addr) == PR_FAILURE) {
   426         fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   427         goto exit;
   428 	}
   429 	if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
   430 		PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
   431 								&tcp_server_addr.ipv6.ip);
   433     /*
   434      * Wake up parent thread because server address is bound and made
   435      * available in the global variable 'tcp_server_addr'
   436      */
   437     PR_PostSem(sp->addr_sem);
   439     for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) {
   440         /* test both null and non-null 'addr' argument to PR_Accept */
   441         PRNetAddr *addrp = (i%2 ? &netaddr: NULL);
   443     DPRINTF(("TCP_Server: Accepting connection\n"));
   444         if ((newsockfd = PR_Accept(sockfd, addrp,
   445             PR_INTERVAL_NO_TIMEOUT)) == NULL) {
   446             fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n");
   447             goto exit;
   448         }
   449     DPRINTF(("TCP_Server: Accepted connection\n"));
   450         scp = PR_NEW(Serve_Client_Param);
   451         if (scp == NULL) {
   452             fprintf(stderr,"prsocket_test: PR_NEW failed\n");
   453             goto exit;
   454         }
   456         /*
   457          * Start a Serve_Client thread for each incoming connection
   458          */
   459         scp->sockfd = newsockfd;
   460         scp->datalen = sp->datalen;
   462         t = create_new_thread(PR_USER_THREAD,
   463             Serve_Client, (void *)scp, 
   464             PR_PRIORITY_NORMAL,
   465             PR_LOCAL_THREAD,
   466             PR_UNJOINABLE_THREAD,
   467             0, i);
   468         if (t == NULL) {
   469             fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
   470             failed_already=1;
   471             goto exit;
   472         }
   473         DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t));
   474     }
   476 exit:
   477     if (sockfd) {
   478         PR_Close(sockfd);
   479     }
   481     /*
   482      * Decrement exit_counter and notify parent thread
   483      */
   485     PR_EnterMonitor(sp->exit_mon);
   486     --(*sp->exit_counter);
   487     PR_Notify(sp->exit_mon);
   488     PR_ExitMonitor(sp->exit_mon);
   489     DPRINTF(("TCP_Server [0x%lx] exiting\n", PR_GetCurrentThread()));
   490 }
   492 /*
   493  * UDP Server
   494  *    Server Thread
   495  *    Bind an address to a socket, read data from clients and send data
   496  *    back to clients
   497  */
   498 static void PR_CALLBACK
   499 UDP_Server(void *arg)
   500 {
   501     Server_Param *sp = (Server_Param *) arg;
   502     PRFileDesc *sockfd;
   503     buffer *in_buf;
   504     PRNetAddr netaddr;
   505     PRInt32 bytes, i, rv = 0;
   508     bytes = sp->datalen;
   509     /*
   510      * Create a udp socket
   511      */
   512 	if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) {
   513         fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n");
   514         failed_already=1;
   515         return;
   516     }
   517     memset(&netaddr, 0 , sizeof(netaddr));
   518 	if (PR_SetNetAddr(PR_IpAddrAny, server_domain, UDP_SERVER_PORT,
   519 									&netaddr) == PR_FAILURE) {
   520         fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   521         failed_already=1;
   522         return;
   523 	}
   524     /*
   525      * try a few times to bind server's address, if addresses are in
   526      * use
   527      */
   528     i = 0;
   529     while (PR_Bind(sockfd, &netaddr) < 0) {
   530         if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
   531             netaddr.inet.port += 2;
   532             if (i++ < SERVER_MAX_BIND_COUNT)
   533                 continue;
   534         }
   535         fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
   536         perror("PR_Bind");
   537         failed_already=1;
   538         return;
   539     }
   541     if (PR_GetSockName(sockfd, &netaddr) < 0) {
   542         fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
   543         failed_already=1;
   544         return;
   545     }
   547     DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
   548         netaddr.inet.ip, netaddr.inet.port));
   549     /*
   550      * We can't use the IP address returned by PR_GetSockName in
   551      * netaddr.inet.ip because netaddr.inet.ip is returned
   552      * as 0 (= PR_INADDR_ANY).
   553      */
   555 	if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
   556 									PR_ntohs(PR_NetAddrInetPort(&netaddr)),
   557 									&udp_server_addr) == PR_FAILURE) {
   558         fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   559         failed_already=1;
   560         return;
   561 	}
   562 	if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
   563 		PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
   564 								&udp_server_addr.ipv6.ip);
   566     /*
   567      * Wake up parent thread because server address is bound and made
   568      * available in the global variable 'udp_server_addr'
   569      */
   570     PR_PostSem(sp->addr_sem);
   572     bytes = sp->datalen;
   573     in_buf = PR_NEW(buffer);
   574     if (in_buf == NULL) {
   575         fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   576         failed_already=1;
   577         return;
   578     }
   579     /*
   580      * Receive datagrams from clients and send them back, unmodified, to the
   581      * clients
   582      */
   583     memset(&netaddr, 0 , sizeof(netaddr));
   584     for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) {
   585         DPRINTF(("UDP_Server: calling PR_RecvFrom client  - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
   586             netaddr.inet.ip, netaddr.inet.port, bytes, in_buf->data,
   587             in_buf->data[0]));
   589         rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
   590             PR_INTERVAL_NO_TIMEOUT);
   591         DPRINTF(("UDP_Server: PR_RecvFrom client  - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
   592             netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data,
   593             in_buf->data[0]));
   594         if (rv != bytes) {
   595             return;
   596         }
   597         rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr,
   598             PR_INTERVAL_NO_TIMEOUT);
   599         if (rv != bytes) {
   600             return;
   601         }
   602     }
   604     PR_DELETE(in_buf);
   605     PR_Close(sockfd);
   607     /*
   608      * Decrement exit_counter and notify parent thread
   609      */
   610     PR_EnterMonitor(sp->exit_mon);
   611     --(*sp->exit_counter);
   612     PR_Notify(sp->exit_mon);
   613     PR_ExitMonitor(sp->exit_mon);
   614     DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread()));
   615 }
   617 /*
   618  * TCP_Client
   619  *    Client Thread
   620  *    Connect to the server at the address specified in the argument.
   621  *    Fill in a buffer, write data to server, read it back and check
   622  *    for data corruption.
   623  *    Close the socket for server connection
   624  */
   625 static void PR_CALLBACK
   626 TCP_Client(void *arg)
   627 {
   628     Client_Param *cp = (Client_Param *) arg;
   629     PRFileDesc *sockfd;
   630     buffer *in_buf, *out_buf;
   631     union PRNetAddr netaddr;
   632     PRInt32 bytes, i, j;
   635     bytes = cp->datalen;
   636     out_buf = PR_NEW(buffer);
   637     if (out_buf == NULL) {
   638         fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   639         failed_already=1;
   640         return;
   641     }
   642     in_buf = PR_NEW(buffer);
   643     if (in_buf == NULL) {
   644         fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   645         failed_already=1;
   646         return;
   647     }
   648     netaddr = cp->server_addr;
   650     for (i = 0; i < num_tcp_connections_per_client; i++) {
   651         if ((sockfd = PR_OpenTCPSocket(client_domain)) == NULL) {
   652             fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n");
   653             failed_already=1;
   654             return;
   655         }
   656         if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
   657         	fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n",
   658             		PR_GetError(), PR_GetOSError());
   659             failed_already=1;
   660             return;
   661         }
   662         for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
   663             /*
   664              * fill in random data
   665              */
   666             memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes);
   667             /*
   668              * write to server
   669              */
   670 #ifdef WINNT
   671 			if (test_cancelio && (j == 0))
   672 				PR_Sleep(PR_SecondsToInterval(12));
   673 #endif
   674             if (writen(sockfd, out_buf->data, bytes) < bytes) {
   675                 fprintf(stderr,"prsocket_test: ERROR - TCP_Client:writen\n");
   676                 failed_already=1;
   677                 return;
   678             }
   679             DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
   680                 PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
   681             if (readn(sockfd, in_buf->data, bytes) < bytes) {
   682                 fprintf(stderr,"prsocket_test: ERROR - TCP_Client:readn\n");
   683                 failed_already=1;
   684                 return;
   685             }
   686             /*
   687              * verify the data read
   688              */
   689             if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
   690                 fprintf(stderr,"prsocket_test: ERROR - data corruption\n");
   691                 failed_already=1;
   692                 return;
   693             }
   694         }
   695         /*
   696          * shutdown reads and writes
   697          */
   698         if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
   699             fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
   700 #if defined(SYMBIAN)
   701             if (EPIPE != errno)
   702 #endif
   703             failed_already=1;
   704         }
   705         PR_Close(sockfd);
   706     }
   708     PR_DELETE(out_buf);
   709     PR_DELETE(in_buf);
   711     /*
   712      * Decrement exit_counter and notify parent thread
   713      */
   715     PR_EnterMonitor(cp->exit_mon);
   716     --(*cp->exit_counter);
   717     PR_Notify(cp->exit_mon);
   718     PR_ExitMonitor(cp->exit_mon);
   719     DPRINTF(("TCP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
   720 }
   722 /*
   723  * UDP_Client
   724  *    Client Thread
   725  *    Create a socket and bind an address 
   726  *    Communicate with the server at the address specified in the argument.
   727  *    Fill in a buffer, write data to server, read it back and check
   728  *    for data corruption.
   729  *    Close the socket
   730  */
   731 static void PR_CALLBACK
   732 UDP_Client(void *arg)
   733 {
   734     Client_Param *cp = (Client_Param *) arg;
   735     PRFileDesc *sockfd;
   736     buffer *in_buf, *out_buf;
   737     union PRNetAddr netaddr;
   738     PRInt32 bytes, i, rv;
   741     bytes = cp->datalen;
   742     out_buf = PR_NEW(buffer);
   743     if (out_buf == NULL) {
   744         fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   745         failed_already=1;
   746         return;
   747     }
   748     in_buf = PR_NEW(buffer);
   749     if (in_buf == NULL) {
   750         fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
   751         failed_already=1;
   752         return;
   753     }
   754     if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) {
   755         fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n");
   756         failed_already=1;
   757         return;
   758     }
   760     /*
   761      * bind an address for the client, let the system chose the port
   762      * number
   763      */
   764     memset(&netaddr, 0 , sizeof(netaddr));
   765 	if (PR_SetNetAddr(PR_IpAddrAny, client_domain, 0,
   766 									&netaddr) == PR_FAILURE) {
   767         fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
   768         failed_already=1;
   769         return;
   770 	}
   771     if (PR_Bind(sockfd, &netaddr) < 0) {
   772         fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
   773         perror("PR_Bind");
   774         return;
   775     }
   777     if (PR_GetSockName(sockfd, &netaddr) < 0) {
   778         fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
   779         failed_already=1;
   780         return;
   781     }
   783     DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
   784         netaddr.inet.ip, netaddr.inet.port));
   786     netaddr = cp->server_addr;
   788     if (cp->udp_connect) {
   789         if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
   790             fprintf(stderr,"prsocket_test: PR_Connect failed\n");
   791             failed_already=1;
   792             return;
   793         }
   794     }
   796     for (i = 0; i < num_udp_datagrams_per_client; i++) {
   797         /*
   798          * fill in random data
   799          */
   800         DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n",
   801             PR_GetCurrentThread(), out_buf->data, bytes));
   802         memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes);
   803         /*
   804          * write to server
   805          */
   806         if (cp->udp_connect)
   807             rv = PR_Send(sockfd, out_buf->data, bytes, 0,
   808                 PR_INTERVAL_NO_TIMEOUT);
   809         else
   810             rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr,
   811                 PR_INTERVAL_NO_TIMEOUT);
   812         if (rv != bytes) {
   813             return;
   814         }
   815         DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
   816             PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
   817         if (cp->udp_connect)
   818             rv = PR_Recv(sockfd, in_buf->data, bytes, 0,
   819                 PR_INTERVAL_NO_TIMEOUT);
   820         else
   821             rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
   822                 PR_INTERVAL_NO_TIMEOUT);
   823         if (rv != bytes) {
   824             return;
   825         }
   826         DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n",
   827             PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data))));
   828         /*
   829          * verify the data read
   830          */
   831         if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
   832             fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n");
   833             failed_already=1;
   834             return;
   835         }
   836     }
   837     PR_Close(sockfd);
   839     PR_DELETE(in_buf);
   840     PR_DELETE(out_buf);
   842     /*
   843      * Decrement exit_counter and notify parent thread
   844      */
   846     PR_EnterMonitor(cp->exit_mon);
   847     --(*cp->exit_counter);
   848     PR_Notify(cp->exit_mon);
   849     PR_ExitMonitor(cp->exit_mon);
   850     PR_DELETE(cp);
   851     DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
   852 }
   854 /*
   855  * TCP_Socket_Client_Server_Test    - concurrent server test
   856  *    
   857  *    One server and several clients are started
   858  *    Each client connects to the server and sends a chunk of data
   859  *    For each connection, server starts another thread to read the data
   860  *    from the client and send it back to the client, unmodified.
   861  *    Each client checks that data received from server is same as the
   862  *    data it sent to the server.
   863  *
   864  */
   866 static PRInt32
   867 TCP_Socket_Client_Server_Test(void)
   868 {
   869     int i;
   870     PRThread *t;
   871     PRSemaphore *server_sem;
   872     Server_Param *sparamp;
   873     Client_Param *cparamp;
   874     PRMonitor *mon2;
   875     PRInt32    datalen;
   878     datalen = tcp_mesg_size;
   879     thread_count = 0;
   880     /*
   881      * start the server thread
   882      */
   883     sparamp = PR_NEW(Server_Param);
   884     if (sparamp == NULL) {
   885         fprintf(stderr,"prsocket_test: PR_NEW failed\n");
   886         failed_already=1;
   887         return -1;
   888     }
   889     server_sem = PR_NewSem(0);
   890     if (server_sem == NULL) {
   891         fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
   892         failed_already=1;
   893         return -1;
   894     }
   895     mon2 = PR_NewMonitor();
   896     if (mon2 == NULL) {
   897         fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
   898         failed_already=1;
   899         return -1;
   900     }
   901     PR_EnterMonitor(mon2);
   903     sparamp->addr_sem = server_sem;
   904     sparamp->exit_mon = mon2;
   905     sparamp->exit_counter = &thread_count;
   906     sparamp->datalen = datalen;
   907     t = PR_CreateThread(PR_USER_THREAD,
   908         TCP_Server, (void *)sparamp, 
   909         PR_PRIORITY_NORMAL,
   910         PR_LOCAL_THREAD,
   911         PR_UNJOINABLE_THREAD,
   912         0);
   913     if (t == NULL) {
   914         fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
   915         failed_already=1;
   916         return -1;
   917     }
   918     DPRINTF(("Created TCP server = 0x%lx\n", t));
   919     thread_count++;
   921     /*
   922      * wait till the server address is setup
   923      */
   924     PR_WaitSem(server_sem);
   926     /*
   927      * Now start a bunch of client threads
   928      */
   930     cparamp = PR_NEW(Client_Param);
   931     if (cparamp == NULL) {
   932         fprintf(stderr,"prsocket_test: PR_NEW failed\n");
   933         failed_already=1;
   934         return -1;
   935     }
   936     cparamp->server_addr = tcp_server_addr;
   937     cparamp->exit_mon = mon2;
   938     cparamp->exit_counter = &thread_count;
   939     cparamp->datalen = datalen;
   940     for (i = 0; i < num_tcp_clients; i++) {
   941         t = create_new_thread(PR_USER_THREAD,
   942             TCP_Client, (void *) cparamp,
   943             PR_PRIORITY_NORMAL,
   944             PR_LOCAL_THREAD,
   945             PR_UNJOINABLE_THREAD,
   946             0, i);
   947         if (t == NULL) {
   948             fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
   949             failed_already=1;
   950             return -1;
   951         }
   952         DPRINTF(("Created TCP client = 0x%lx\n", t));
   953         thread_count++;
   954     }
   955     /* Wait for server and client threads to exit */
   956     while (thread_count) {
   957         PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
   958         DPRINTF(("TCP Server - thread_count  = %d\n", thread_count));
   959     }
   960     PR_ExitMonitor(mon2);
   961     printf("%30s","TCP_Socket_Client_Server_Test:");
   962     printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
   963         num_tcp_clients, num_tcp_connections_per_client);
   964     printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
   965         num_tcp_mesgs_per_connection, tcp_mesg_size);
   967     return 0;
   968 }
   970 /*
   971  * UDP_Socket_Client_Server_Test    - iterative server test
   972  *    
   973  *    One server and several clients are started
   974  *    Each client connects to the server and sends a chunk of data
   975  *    For each connection, server starts another thread to read the data
   976  *    from the client and send it back to the client, unmodified.
   977  *    Each client checks that data received from server is same as the
   978  *    data it sent to the server.
   979  *
   980  */
   982 static PRInt32
   983 UDP_Socket_Client_Server_Test(void)
   984 {
   985     int i;
   986     PRThread *t;
   987     PRSemaphore *server_sem;
   988     Server_Param *sparamp;
   989     Client_Param *cparamp;
   990     PRMonitor *mon2;
   991     PRInt32    datalen;
   992     PRInt32    udp_connect = 1;
   995     datalen = udp_datagram_size;
   996     thread_count = 0;
   997     /*
   998      * start the server thread
   999      */
  1000     sparamp = PR_NEW(Server_Param);
  1001     if (sparamp == NULL) {
  1002         fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1003         failed_already=1;
  1004         return -1;
  1006     server_sem = PR_NewSem(0);
  1007     if (server_sem == NULL) {
  1008         fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
  1009         failed_already=1;
  1010         return -1;
  1012     mon2 = PR_NewMonitor();
  1013     if (mon2 == NULL) {
  1014         fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
  1015         failed_already=1;
  1016         return -1;
  1018     PR_EnterMonitor(mon2);
  1020     sparamp->addr_sem = server_sem;
  1021     sparamp->exit_mon = mon2;
  1022     sparamp->exit_counter = &thread_count;
  1023     sparamp->datalen = datalen;
  1024     DPRINTF(("Creating UDP server"));
  1025     t = PR_CreateThread(PR_USER_THREAD,
  1026         UDP_Server, (void *)sparamp, 
  1027         PR_PRIORITY_NORMAL,
  1028         PR_LOCAL_THREAD,
  1029         PR_UNJOINABLE_THREAD,
  1030         0);
  1031     if (t == NULL) {
  1032         fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  1033         failed_already=1;
  1034         return -1;
  1036     thread_count++;
  1038     /*
  1039      * wait till the server address is setup
  1040      */
  1041     PR_WaitSem(server_sem);
  1043     /*
  1044      * Now start a bunch of client threads
  1045      */
  1047     for (i = 0; i < num_udp_clients; i++) {
  1048         cparamp = PR_NEW(Client_Param);
  1049         if (cparamp == NULL) {
  1050             fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1051             failed_already=1;
  1052             return -1;
  1054         cparamp->server_addr = udp_server_addr;
  1055         cparamp->exit_mon = mon2;
  1056         cparamp->exit_counter = &thread_count;
  1057         cparamp->datalen = datalen;
  1058         /*
  1059          * Cause every other client thread to connect udp sockets
  1060          */
  1061         cparamp->udp_connect = udp_connect;
  1062         if (udp_connect)
  1063             udp_connect = 0;
  1064         else
  1065             udp_connect = 1;
  1066         DPRINTF(("Creating UDP client %d\n", i));
  1067         t = PR_CreateThread(PR_USER_THREAD,
  1068             UDP_Client, (void *) cparamp,
  1069             PR_PRIORITY_NORMAL,
  1070             PR_LOCAL_THREAD,
  1071             PR_UNJOINABLE_THREAD,
  1072             0);
  1073         if (t == NULL) {
  1074             fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  1075             failed_already=1;
  1076             return -1;
  1078         thread_count++;
  1080     /* Wait for server and client threads to exit */
  1081     while (thread_count) {
  1082         PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
  1083         DPRINTF(("UDP Server - thread_count  = %d\n", thread_count));
  1085     PR_ExitMonitor(mon2);
  1086     printf("%30s","UDP_Socket_Client_Server_Test: ");
  1087     printf("%2ld Server %2ld Clients\n",1l, num_udp_clients);
  1088     printf("%30s %2ld datagrams_per_client %4ld bytes_per_datagram\n",":",
  1089         num_udp_datagrams_per_client, udp_datagram_size);
  1091     return 0;
  1094 static PRFileDesc *small_file_fd, *large_file_fd;
  1095 static void *small_file_addr, *small_file_header, *large_file_addr;
  1096 static void *small_file_trailer, *large_file_header, *large_file_trailer;
  1097 /*
  1098  * TransmitFile_Client
  1099  *    Client Thread
  1100  */
  1101 static void
  1102 TransmitFile_Client(void *arg)
  1104     PRFileDesc *sockfd;
  1105     union PRNetAddr netaddr;
  1106     char *small_buf, *large_buf;
  1107     Client_Param *cp = (Client_Param *) arg;
  1108 	PRInt32 rlen;
  1110     small_buf = (char*)PR_Malloc(SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
  1111 										SMALL_FILE_TRAILER_SIZE);
  1112     if (small_buf == NULL) {
  1113         fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
  1114         failed_already=1;
  1115         return;
  1117     large_buf = (char*)PR_Malloc(LARGE_FILE_SIZE + LARGE_FILE_HEADER_SIZE +
  1118 												LARGE_FILE_TRAILER_SIZE);
  1119     if (large_buf == NULL) {
  1120         fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
  1121         failed_already=1;
  1122         return;
  1124     netaddr.inet.family = cp->server_addr.inet.family;
  1125     netaddr.inet.port = cp->server_addr.inet.port;
  1126     netaddr.inet.ip = cp->server_addr.inet.ip;
  1128     if ((sockfd = PR_NewTCPSocket()) == NULL) {
  1129         fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
  1130         failed_already=1;
  1131         return;
  1134     if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
  1135         fprintf(stderr,"prsocket_test: PR_Connect failed\n");
  1136         failed_already=1;
  1137         return;
  1139     /*
  1140      * read the small file and verify the data
  1141      */
  1142     if (readn(sockfd, small_buf, SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)
  1143         != (SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)) {
  1144         fprintf(stderr,
  1145             "prsocket_test: TransmitFile_Client failed to receive file\n");
  1146         failed_already=1;
  1147         return;
  1149 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1150     /* File transmission test can not be done because of large file's size */
  1151     if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1152         fprintf(stderr,
  1153             "prsocket_test: TransmitFile_Client ERROR - small file header data corruption\n");
  1154         failed_already=1;
  1155         return;
  1157     if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
  1158         SMALL_FILE_SIZE) != 0) {
  1159         fprintf(stderr,
  1160             "prsocket_test: TransmitFile_Client ERROR - small file data corruption\n");
  1161         failed_already=1;
  1162         return;
  1164 #endif
  1165     /*
  1166      * read the large file and verify the data
  1167      */
  1168     if (readn(sockfd, large_buf, LARGE_FILE_SIZE) != LARGE_FILE_SIZE) {
  1169         fprintf(stderr,
  1170             "prsocket_test: TransmitFile_Client failed to receive file\n");
  1171         failed_already=1;
  1172         return;
  1174 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1175     if (memcmp(large_file_addr, large_buf, LARGE_FILE_SIZE) != 0) {
  1176         fprintf(stderr,
  1177             "prsocket_test: TransmitFile_Client ERROR - large file data corruption\n");
  1178         failed_already=1;
  1180 #endif
  1183 	/*
  1184 	 * receive data from PR_SendFile
  1185 	 */
  1186 	/*
  1187 	 * case 1: small file with header and trailer
  1188 	 */
  1189     rlen = SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
  1190 									SMALL_FILE_TRAILER_SIZE;
  1191     if (readn(sockfd, small_buf, rlen) != rlen) {
  1192         fprintf(stderr,
  1193             "prsocket_test: SendFile_Client failed to receive file\n");
  1194         failed_already=1;
  1195         return;
  1197 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1198     if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1199         fprintf(stderr,
  1200             "SendFile 1. ERROR - small file header corruption\n");
  1201         failed_already=1;
  1202         return;
  1204     if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
  1205         								SMALL_FILE_SIZE) != 0) {
  1206         fprintf(stderr,
  1207             "SendFile 1. ERROR - small file data corruption\n");
  1208         failed_already=1;
  1209         return;
  1211     if (memcmp(small_file_trailer,
  1212 				small_buf + SMALL_FILE_HEADER_SIZE + SMALL_FILE_SIZE,
  1213         				SMALL_FILE_TRAILER_SIZE) != 0) {
  1214         fprintf(stderr,
  1215             "SendFile 1. ERROR - small file trailer corruption\n");
  1216         failed_already=1;
  1217         return;
  1219 #endif
  1220 	/*
  1221 	 * case 2: partial large file at zero offset, file with header and trailer
  1222 	 */
  1223     rlen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
  1224 									LARGE_FILE_TRAILER_SIZE;
  1225     if (readn(sockfd, large_buf, rlen) != rlen) {
  1226         fprintf(stderr,
  1227             "prsocket_test: SendFile_Client failed to receive file\n");
  1228         failed_already=1;
  1229         return;
  1231 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1232     if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1233         fprintf(stderr,
  1234             "SendFile 2. ERROR - large file header corruption\n");
  1235         failed_already=1;
  1236         return;
  1238     if (memcmp(large_file_addr, large_buf + LARGE_FILE_HEADER_SIZE,
  1239         								LARGE_FILE_LEN_1) != 0) {
  1240         fprintf(stderr,
  1241             "SendFile 2. ERROR - large file data corruption\n");
  1242         failed_already=1;
  1243         return;
  1245     if (memcmp(large_file_trailer,
  1246 				large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_1,
  1247         				LARGE_FILE_TRAILER_SIZE) != 0) {
  1248         fprintf(stderr,
  1249             "SendFile 2. ERROR - large file trailer corruption\n");
  1250         failed_already=1;
  1251         return;
  1253 #endif
  1254 	/*
  1255 	 * case 3: partial small file at non-zero offset, with header
  1256 	 */
  1257     rlen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
  1258     if (readn(sockfd, small_buf, rlen) != rlen) {
  1259         fprintf(stderr,
  1260             "prsocket_test: SendFile_Client failed to receive file\n");
  1261         failed_already=1;
  1262         return;
  1264 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1265     if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1266         fprintf(stderr,
  1267             "SendFile 3. ERROR - small file header corruption\n");
  1268         failed_already=1;
  1269         return;
  1271     if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_1,
  1272 				small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_1) != 0) {
  1273         fprintf(stderr,
  1274             "SendFile 3. ERROR - small file data corruption\n");
  1275         failed_already=1;
  1276         return;
  1278 #endif
  1279 	/*
  1280 	 * case 4: partial small file at non-zero offset, with trailer
  1281 	 */
  1282     rlen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
  1283     if (readn(sockfd, small_buf, rlen) != rlen) {
  1284         fprintf(stderr,
  1285             "prsocket_test: SendFile_Client failed to receive file\n");
  1286         failed_already=1;
  1287         return;
  1289 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1290     if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_2, small_buf,
  1291         								SMALL_FILE_LEN_2) != 0) {
  1292         fprintf(stderr,
  1293             "SendFile 4. ERROR - small file data corruption\n");
  1294         failed_already=1;
  1295         return;
  1297     if (memcmp(small_file_trailer, small_buf + SMALL_FILE_LEN_2,
  1298         				SMALL_FILE_TRAILER_SIZE) != 0) {
  1299         fprintf(stderr,
  1300             "SendFile 4. ERROR - small file trailer corruption\n");
  1301         failed_already=1;
  1302         return;
  1304 #endif
  1305 	/*
  1306 	 * case 5: partial large file at non-zero offset, file with header
  1307 	 */
  1308     rlen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE;
  1309     if (readn(sockfd, large_buf, rlen) != rlen) {
  1310         fprintf(stderr,
  1311             "prsocket_test: SendFile_Client failed to receive file\n");
  1312         failed_already=1;
  1313         return;
  1315 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1316     if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1317         fprintf(stderr,
  1318             "SendFile 5. ERROR - large file header corruption\n");
  1319         failed_already=1;
  1320         return;
  1322     if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_2,
  1323 					large_buf + LARGE_FILE_HEADER_SIZE,
  1324         								LARGE_FILE_LEN_2) != 0) {
  1325         fprintf(stderr,
  1326             "SendFile 5. ERROR - large file data corruption\n");
  1327         failed_already=1;
  1328         return;
  1330 #endif
  1331 	/*
  1332 	 * case 6: partial small file at non-zero offset, with header
  1333 	 */
  1334     rlen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE;
  1335     if (readn(sockfd, small_buf, rlen) != rlen) {
  1336         fprintf(stderr,
  1337             "prsocket_test: SendFile_Client failed to receive file\n");
  1338         failed_already=1;
  1339         return;
  1341 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1342     if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1343         fprintf(stderr,
  1344             "SendFile 6. ERROR - small file header corruption\n");
  1345         return;
  1347     if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_3,
  1348 				small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_3) != 0) {
  1349 #if 0
  1350 		char *i, *j;
  1351 		int k;
  1353 		i = (char *) small_file_addr + SMALL_FILE_OFFSET_3;
  1354 		j = small_buf + SMALL_FILE_HEADER_SIZE;
  1355 		k = SMALL_FILE_LEN_3;
  1356 		while (k-- > 0) {
  1357 			if (*i++ != *j++)
  1358 			printf("i = %d j = %d\n",
  1359 				(int) (i - ((char *) small_file_addr + SMALL_FILE_OFFSET_3)),
  1360 				(int) (j - (small_buf + SMALL_FILE_HEADER_SIZE)));
  1362 #endif
  1363         fprintf(stderr,
  1364             "SendFile 6. ERROR - small file data corruption\n");
  1365         failed_already=1;
  1366         return;
  1368 #endif
  1369 	/*
  1370 	 * case 7: partial large file at non-zero offset, with header
  1371 	 */
  1372     rlen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE;
  1373     if (readn(sockfd, large_buf, rlen) != rlen) {
  1374         fprintf(stderr,
  1375             "prsocket_test: SendFile_Client failed to receive file\n");
  1376         failed_already=1;
  1377         return;
  1379 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1380     if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1381         fprintf(stderr,
  1382             "SendFile 7. ERROR - large file header corruption\n");
  1383         failed_already=1;
  1384         return;
  1386     if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_3,
  1387 					large_buf + LARGE_FILE_HEADER_SIZE,
  1388         								LARGE_FILE_LEN_3) != 0) {
  1389         fprintf(stderr,
  1390             "SendFile 7. ERROR - large file data corruption\n");
  1391         failed_already=1;
  1392         return;
  1394 #endif
  1395 	/*
  1396 	 * case 8: partial large file at non-zero, page-aligned offset, with
  1397 	 * header and trailer
  1398 	 */
  1399     rlen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE +
  1400 									LARGE_FILE_TRAILER_SIZE;
  1401     if (readn(sockfd, large_buf, rlen) != rlen) {
  1402         fprintf(stderr,
  1403             "prsocket_test: SendFile_Client failed to receive file\n");
  1404         failed_already=1;
  1405         return;
  1407 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1408     if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1409         fprintf(stderr,
  1410             "SendFile 2. ERROR - large file header corruption\n");
  1411         failed_already=1;
  1412         return;
  1414     if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_4,
  1415 				large_buf + LARGE_FILE_HEADER_SIZE,
  1416         								LARGE_FILE_LEN_4) != 0) {
  1417         fprintf(stderr,
  1418             "SendFile 2. ERROR - large file data corruption\n");
  1419         failed_already=1;
  1420         return;
  1422     if (memcmp(large_file_trailer,
  1423 				large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_4,
  1424         				LARGE_FILE_TRAILER_SIZE) != 0) {
  1425         fprintf(stderr,
  1426             "SendFile 2. ERROR - large file trailer corruption\n");
  1427         failed_already=1;
  1428         return;
  1430 #endif
  1431     PR_DELETE(small_buf);
  1432     PR_DELETE(large_buf);
  1433     PR_Close(sockfd);
  1436     /*
  1437      * Decrement exit_counter and notify parent thread
  1438      */
  1440     PR_EnterMonitor(cp->exit_mon);
  1441     --(*cp->exit_counter);
  1442     PR_Notify(cp->exit_mon);
  1443     PR_ExitMonitor(cp->exit_mon);
  1444     DPRINTF(("TransmitFile_Client [0x%lx] exiting\n", PR_GetCurrentThread()));
  1447 /*
  1448  * Serve_TransmitFile_Client
  1449  *    Thread, started by the server, for serving a client connection.
  1450  *    Trasmits a small file, with a header, and a large file, without
  1451  *    a header
  1452  */
  1453 static void
  1454 Serve_TransmitFile_Client(void *arg)
  1456     Serve_Client_Param *scp = (Serve_Client_Param *) arg;
  1457     PRFileDesc *sockfd;
  1458     PRInt32 bytes;
  1459     PRFileDesc *local_small_file_fd=NULL;
  1460     PRFileDesc *local_large_file_fd=NULL;
  1461 	PRSendFileData sfd;
  1462 	PRInt32 slen;
  1464     sockfd = scp->sockfd;
  1465     local_small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDONLY,0);
  1467     if (local_small_file_fd == NULL) {
  1468         fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
  1469             SMALL_FILE_NAME);
  1470         failed_already=1;
  1471         goto done;
  1473     local_large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDONLY,0);
  1475     if (local_large_file_fd == NULL) {
  1476         fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
  1477             LARGE_FILE_NAME);
  1478         failed_already=1;
  1479         goto done;
  1481     bytes = PR_TransmitFile(sockfd, local_small_file_fd, small_file_header,
  1482         SMALL_FILE_HEADER_SIZE, PR_TRANSMITFILE_KEEP_OPEN,
  1483         PR_INTERVAL_NO_TIMEOUT);
  1484     if (bytes != (SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE)) {
  1485         fprintf(stderr,
  1486             "prsocet_test: PR_TransmitFile failed: (%ld, %ld)\n",
  1487             PR_GetError(), PR_GetOSError());
  1488         failed_already=1;
  1490     bytes = PR_TransmitFile(sockfd, local_large_file_fd, NULL, 0,
  1491         PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT);
  1492     if (bytes != LARGE_FILE_SIZE) {
  1493         fprintf(stderr,
  1494             "prsocket_test: PR_TransmitFile failed: (%ld, %ld)\n",
  1495             PR_GetError(), PR_GetOSError());
  1496         failed_already=1;
  1499 	/*
  1500 	 * PR_SendFile test cases
  1501 	 */
  1503 	/*
  1504 	 * case 1: small file with header and trailer
  1505 	 */
  1506 	sfd.fd = local_small_file_fd;
  1507 	sfd.file_offset = 0;
  1508 	sfd.file_nbytes = 0;
  1509 	sfd.header = small_file_header;
  1510 	sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1511 	sfd.trailer = small_file_trailer;
  1512 	sfd.tlen = SMALL_FILE_TRAILER_SIZE;
  1513     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1514         				PR_INTERVAL_NO_TIMEOUT);
  1515     slen = SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE +
  1516 						SMALL_FILE_TRAILER_SIZE;
  1517     if (bytes != slen) {
  1518         fprintf(stderr,
  1519 			"socket: Error - 1. PR_SendFile  send_size = %d, bytes sent = %d\n",
  1520 									slen, bytes);
  1521         fprintf(stderr,
  1522             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1523             PR_GetError(), PR_GetOSError());
  1524         failed_already=1;
  1527 	/*
  1528 	 * case 2: partial large file at zero offset, file with header and trailer
  1529 	 */
  1530 	sfd.fd = local_large_file_fd;
  1531 	sfd.file_offset = 0;
  1532 	sfd.file_nbytes = LARGE_FILE_LEN_1;
  1533 	sfd.header = large_file_header;
  1534 	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1535 	sfd.trailer = large_file_trailer;
  1536 	sfd.tlen = LARGE_FILE_TRAILER_SIZE;
  1537     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1538         				PR_INTERVAL_NO_TIMEOUT);
  1539     slen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
  1540 						LARGE_FILE_TRAILER_SIZE;
  1541     if (bytes != slen) {
  1542         fprintf(stderr,
  1543 			"socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
  1544 									slen, bytes);
  1545         fprintf(stderr,
  1546             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1547             PR_GetError(), PR_GetOSError());
  1548         failed_already=1;
  1550 	/*
  1551 	 * case 3: partial small file at non-zero offset, with header
  1552 	 */
  1553 	sfd.fd = local_small_file_fd;
  1554 	sfd.file_offset = SMALL_FILE_OFFSET_1;
  1555 	sfd.file_nbytes = SMALL_FILE_LEN_1;
  1556 	sfd.header = small_file_header;
  1557 	sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1558 	sfd.trailer = NULL;
  1559 	sfd.tlen = 0;
  1560     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1561         				PR_INTERVAL_NO_TIMEOUT);
  1562     slen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
  1563     if (bytes != slen) {
  1564         fprintf(stderr,
  1565 			"socket: Error - 3. PR_SendFile send_size = %d, bytes sent = %d\n",
  1566 									slen, bytes);
  1567         fprintf(stderr,
  1568             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1569             PR_GetError(), PR_GetOSError());
  1570         failed_already=1;
  1572 	/*
  1573 	 * case 4: partial small file at non-zero offset, with trailer
  1574 	 */
  1575 	sfd.fd = local_small_file_fd;
  1576 	sfd.file_offset = SMALL_FILE_OFFSET_2;
  1577 	sfd.file_nbytes = SMALL_FILE_LEN_2;
  1578 	sfd.header = NULL;
  1579 	sfd.hlen = 0;
  1580 	sfd.trailer = small_file_trailer;
  1581 	sfd.tlen = SMALL_FILE_TRAILER_SIZE;
  1582     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1583         				PR_INTERVAL_NO_TIMEOUT);
  1584     slen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
  1585     if (bytes != slen) {
  1586         fprintf(stderr,
  1587 			"socket: Error - 4. PR_SendFile send_size = %d, bytes sent = %d\n",
  1588 									slen, bytes);
  1589         fprintf(stderr,
  1590             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1591             PR_GetError(), PR_GetOSError());
  1592         failed_already=1;
  1594 	/*
  1595 	 * case 5: partial large file at non-zero offset, file with header
  1596 	 */
  1597 	sfd.fd = local_large_file_fd;
  1598 	sfd.file_offset = LARGE_FILE_OFFSET_2;
  1599 	sfd.file_nbytes = LARGE_FILE_LEN_2;
  1600 	sfd.header = large_file_header;
  1601 	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1602 	sfd.trailer = NULL;
  1603 	sfd.tlen = 0;
  1604     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1605         				PR_INTERVAL_NO_TIMEOUT);
  1606     slen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE;
  1607     if (bytes != slen) {
  1608         fprintf(stderr,
  1609 			"socket: Error - 5. PR_SendFile send_size = %d, bytes sent = %d\n",
  1610 									slen, bytes);
  1611         fprintf(stderr,
  1612             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1613             PR_GetError(), PR_GetOSError());
  1614         failed_already=1;
  1616 	/*
  1617 	 * case 6: partial small file from non-zero offset till end of file, with header
  1618 	 */
  1619 	sfd.fd = local_small_file_fd;
  1620 	sfd.file_offset = SMALL_FILE_OFFSET_3;
  1621 	sfd.file_nbytes = 0;				/* data from offset to end-of-file */
  1622 	sfd.header = small_file_header;
  1623 	sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1624 	sfd.trailer = NULL;
  1625 	sfd.tlen = 0;
  1626     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1627         				PR_INTERVAL_NO_TIMEOUT);
  1628     slen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE;
  1629     if (bytes != slen) {
  1630         fprintf(stderr,
  1631 			"socket: Error - 6. PR_SendFile send_size = %d, bytes sent = %d\n",
  1632 									slen, bytes);
  1633         fprintf(stderr,
  1634             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1635             PR_GetError(), PR_GetOSError());
  1636         failed_already=1;
  1638 	/*
  1639 	 * case 7: partial large file at non-zero offset till end-of-file, with header
  1640 	 */
  1641 	sfd.fd = local_large_file_fd;
  1642 	sfd.file_offset = LARGE_FILE_OFFSET_3;
  1643 	sfd.file_nbytes = 0;				/* data until end-of-file */
  1644 	sfd.header = large_file_header;
  1645 	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1646 	sfd.trailer = NULL;
  1647 	sfd.tlen = 0;
  1648     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1649         									PR_INTERVAL_NO_TIMEOUT);
  1650     slen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE;
  1651     if (bytes != slen) {
  1652         fprintf(stderr,
  1653 			"socket: Error - 7. PR_SendFile send_size = %d, bytes sent = %d\n",
  1654 									slen, bytes);
  1655         fprintf(stderr,
  1656             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1657             PR_GetError(), PR_GetOSError());
  1658         failed_already=1;
  1660 	/*
  1661 	 * case 8: partial large file at non-zero page-aligned offset,
  1662 	 * with header and trailer
  1663 	 */
  1664 	sfd.fd = local_large_file_fd;
  1665 	sfd.file_offset = LARGE_FILE_OFFSET_4;
  1666 	sfd.file_nbytes = LARGE_FILE_LEN_4;
  1667 	sfd.header = large_file_header;
  1668 	sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1669 	sfd.trailer = large_file_trailer;
  1670 	sfd.tlen = LARGE_FILE_TRAILER_SIZE;
  1671     bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_CLOSE_SOCKET,
  1672         				PR_INTERVAL_NO_TIMEOUT);
  1673     slen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE +
  1674 						LARGE_FILE_TRAILER_SIZE;
  1675     if (bytes != slen) {
  1676         fprintf(stderr,
  1677 			"socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
  1678 									slen, bytes);
  1679         fprintf(stderr,
  1680             "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1681             PR_GetError(), PR_GetOSError());
  1682         failed_already=1;
  1684 done:
  1685     if (local_small_file_fd != NULL)
  1686         PR_Close(local_small_file_fd);
  1687     if (local_large_file_fd != NULL)
  1688         PR_Close(local_large_file_fd);
  1691 /*
  1692  * TransmitFile Server
  1693  *    Server Thread
  1694  *    Bind an address to a socket and listen for incoming connections
  1695  *    Create worker threads to service clients
  1696  */
  1697 static void
  1698 TransmitFile_Server(void *arg)
  1700     PRThread **t = NULL;  /* an array of PRThread pointers */
  1701     Server_Param *sp = (Server_Param *) arg;
  1702     Serve_Client_Param *scp;
  1703     PRFileDesc *sockfd = NULL, *newsockfd;
  1704     PRNetAddr netaddr;
  1705     PRInt32 i;
  1707     t = (PRThread**)PR_MALLOC(num_transmitfile_clients * sizeof(PRThread *));
  1708     if (t == NULL) {
  1709         fprintf(stderr, "prsocket_test: run out of memory\n");
  1710         failed_already=1;
  1711         goto exit;
  1713     /*
  1714      * Create a tcp socket
  1715      */
  1716     if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) {
  1717         fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n");
  1718         failed_already=1;
  1719         goto exit;
  1721     memset(&netaddr, 0 , sizeof(netaddr));
  1722     netaddr.inet.family = PR_AF_INET;
  1723     netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
  1724     netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
  1725     /*
  1726      * try a few times to bind server's address, if addresses are in
  1727      * use
  1728      */
  1729     i = 0;
  1730     while (PR_Bind(sockfd, &netaddr) < 0) {
  1731         if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
  1732             netaddr.inet.port += 2;
  1733             if (i++ < SERVER_MAX_BIND_COUNT)
  1734                 continue;
  1736         fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
  1737         failed_already=1;
  1738         perror("PR_Bind");
  1739         goto exit;
  1742     if (PR_Listen(sockfd, 32) < 0) {
  1743         fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n");
  1744         failed_already=1;
  1745         goto exit;
  1748     if (PR_GetSockName(sockfd, &netaddr) < 0) {
  1749         fprintf(stderr,
  1750             "prsocket_test: ERROR - PR_GetSockName failed\n");
  1751         failed_already=1;
  1752         goto exit;
  1755     DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
  1756         netaddr.inet.ip, netaddr.inet.port));
  1757     tcp_server_addr.inet.family = netaddr.inet.family;
  1758     tcp_server_addr.inet.port = netaddr.inet.port;
  1759     tcp_server_addr.inet.ip = netaddr.inet.ip;
  1761     /*
  1762      * Wake up parent thread because server address is bound and made
  1763      * available in the global variable 'tcp_server_addr'
  1764      */
  1765     PR_PostSem(sp->addr_sem);
  1767     for (i = 0; i < num_transmitfile_clients ; i++) {
  1768         /* test both null and non-null 'addr' argument to PR_Accept */
  1769         PRNetAddr *addrp = (i%2 ? &netaddr: NULL);
  1771         if ((newsockfd = PR_Accept(sockfd, addrp,
  1772             PR_INTERVAL_NO_TIMEOUT)) == NULL) {
  1773             fprintf(stderr,
  1774                 "prsocket_test: ERROR - PR_Accept failed\n");
  1775             failed_already=1;
  1776             goto exit;
  1778         /* test both regular and emulated PR_SendFile */
  1779         if (i%2) {
  1780             PRFileDesc *layer = PR_CreateIOLayerStub(
  1781                 emuSendFileIdentity, &emuSendFileMethods);
  1782             if (layer == NULL) {
  1783                 fprintf(stderr,
  1784                     "prsocket_test: ERROR - PR_CreateIOLayerStub failed\n");
  1785                 failed_already=1;
  1786                 goto exit;
  1788             if (PR_PushIOLayer(newsockfd, PR_TOP_IO_LAYER, layer)
  1789                     == PR_FAILURE) {
  1790                 fprintf(stderr,
  1791                     "prsocket_test: ERROR - PR_PushIOLayer failed\n");
  1792                 failed_already=1;
  1793                 goto exit;
  1796         scp = PR_NEW(Serve_Client_Param);
  1797         if (scp == NULL) {
  1798             fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  1799             failed_already=1;
  1800             goto exit;
  1803         /*
  1804          * Start a Serve_Client thread for each incoming connection
  1805          */
  1806         scp->sockfd = newsockfd;
  1807         scp->datalen = sp->datalen;
  1809         t[i] = PR_CreateThread(PR_USER_THREAD,
  1810             Serve_TransmitFile_Client, (void *)scp, 
  1811             PR_PRIORITY_NORMAL,
  1812             PR_LOCAL_THREAD,
  1813             PR_JOINABLE_THREAD,
  1814             0);
  1815         if (t[i] == NULL) {
  1816             fprintf(stderr,
  1817                 "prsocket_test: PR_CreateThread failed\n");
  1818             failed_already=1;
  1819             goto exit;
  1821         DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t));
  1824     /*
  1825      * Wait for all the worker threads to end, so that we know
  1826      * they are no longer using the small and large file fd's.
  1827      */
  1829     for (i = 0; i < num_transmitfile_clients; i++) {
  1830         PR_JoinThread(t[i]);
  1833 exit:
  1834     if (t) {
  1835         PR_DELETE(t);
  1837     if (sockfd) {
  1838         PR_Close(sockfd);
  1841     /*
  1842      * Decrement exit_counter and notify parent thread
  1843      */
  1845     PR_EnterMonitor(sp->exit_mon);
  1846     --(*sp->exit_counter);
  1847     PR_Notify(sp->exit_mon);
  1848     PR_ExitMonitor(sp->exit_mon);
  1849     DPRINTF(("TransmitFile_Server [0x%lx] exiting\n", PR_GetCurrentThread()));
  1852 /*
  1853  * Socket_Misc_Test    - test miscellaneous functions 
  1855  */
  1856 static PRInt32
  1857 Socket_Misc_Test(void)
  1859     PRIntn i, rv = 0, bytes, count, len;
  1860     PRThread *t;
  1861     PRSemaphore *server_sem;
  1862     Server_Param *sparamp;
  1863     Client_Param *cparamp;
  1864     PRMonitor *mon2;
  1865     PRInt32    datalen;
  1867     /*
  1868  * We deliberately pick a buffer size that is not a nice multiple
  1869  * of 1024.
  1870  */
  1871 #define TRANSMITFILE_BUF_SIZE    (4 * 1024 - 11)
  1873     typedef struct {
  1874         char    data[TRANSMITFILE_BUF_SIZE];
  1875     } file_buf;
  1876     file_buf *buf = NULL;
  1878     /*
  1879      * create file(s) to be transmitted
  1880      */
  1881     if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
  1882         printf("prsocket_test failed to create dir %s\n",TEST_DIR);
  1883         failed_already=1;
  1884         return -1;
  1887     small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777);
  1889     if (small_file_fd == NULL) {
  1890         fprintf(stderr,"prsocket_test failed to create/open file %s\n",
  1891             SMALL_FILE_NAME);
  1892         failed_already=1;
  1893         rv = -1;
  1894         goto done;
  1896     buf = PR_NEW(file_buf);
  1897     if (buf == NULL) {
  1898         fprintf(stderr,"prsocket_test failed to allocate buffer\n");
  1899         failed_already=1;
  1900         rv = -1;
  1901         goto done;
  1903     /*
  1904      * fill in random data
  1905      */
  1906     for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
  1907         buf->data[i] = i;
  1909     count = 0;
  1910     do {
  1911         len = (SMALL_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ?
  1912             TRANSMITFILE_BUF_SIZE : (SMALL_FILE_SIZE - count);
  1913         bytes = PR_Write(small_file_fd, buf->data, len);
  1914         if (bytes <= 0) {
  1915             fprintf(stderr,
  1916                 "prsocket_test failed to write to file %s\n",
  1917                 SMALL_FILE_NAME);
  1918             failed_already=1;
  1919             rv = -1;
  1920             goto done;
  1922         count += bytes;
  1923     } while (count < SMALL_FILE_SIZE);
  1924 #ifdef XP_UNIX
  1925     /*
  1926      * map the small file; used in checking for data corruption
  1927      */
  1928     small_file_addr = mmap(0, SMALL_FILE_SIZE, PROT_READ,
  1929         MAP_SHARED, small_file_fd->secret->md.osfd, 0);
  1930     if (small_file_addr == (void *) -1) {
  1931         fprintf(stderr,"prsocket_test failed to mmap file %s\n",
  1932             SMALL_FILE_NAME);
  1933         failed_already=1;
  1934         rv = -1;
  1935         goto done;
  1937 #endif
  1938     /*
  1939      * header for small file
  1940      */
  1941     small_file_header = PR_MALLOC(SMALL_FILE_HEADER_SIZE);
  1942     if (small_file_header == NULL) {
  1943         fprintf(stderr,"prsocket_test failed to malloc header file\n");
  1944         failed_already=1;
  1945         rv = -1;
  1946         goto done;
  1948     memset(small_file_header, (int) PR_IntervalNow(),
  1949         SMALL_FILE_HEADER_SIZE);
  1950     /*
  1951      * trailer for small file
  1952      */
  1953     small_file_trailer = PR_MALLOC(SMALL_FILE_TRAILER_SIZE);
  1954     if (small_file_trailer == NULL) {
  1955         fprintf(stderr,"prsocket_test failed to malloc header trailer\n");
  1956         failed_already=1;
  1957         rv = -1;
  1958         goto done;
  1960     memset(small_file_trailer, (int) PR_IntervalNow(),
  1961         SMALL_FILE_TRAILER_SIZE);
  1962     /*
  1963      * setup large file
  1964      */
  1965     large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777);
  1967     if (large_file_fd == NULL) {
  1968         fprintf(stderr,"prsocket_test failed to create/open file %s\n",
  1969             LARGE_FILE_NAME);
  1970         failed_already=1;
  1971         rv = -1;
  1972         goto done;
  1974     /*
  1975      * fill in random data
  1976      */
  1977     for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
  1978         buf->data[i] = i;
  1980     count = 0;
  1981     do {
  1982         len = (LARGE_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ?
  1983             TRANSMITFILE_BUF_SIZE : (LARGE_FILE_SIZE - count);
  1984         bytes = PR_Write(large_file_fd, buf->data, len);
  1985         if (bytes <= 0) {
  1986             fprintf(stderr,
  1987                 "prsocket_test failed to write to file %s: (%ld, %ld)\n",
  1988                 LARGE_FILE_NAME,
  1989                 PR_GetError(), PR_GetOSError());
  1990             failed_already=1;
  1991             rv = -1;
  1992             goto done;
  1994         count += bytes;
  1995     } while (count < LARGE_FILE_SIZE);
  1996 #if defined(XP_UNIX) && !defined(SYMBIAN)
  1997     /*
  1998      * map the large file; used in checking for data corruption
  1999      */
  2000     large_file_addr = mmap(0, LARGE_FILE_SIZE, PROT_READ,
  2001         MAP_SHARED, large_file_fd->secret->md.osfd, 0);
  2002     if (large_file_addr == (void *) -1) {
  2003         fprintf(stderr,"prsocket_test failed to mmap file %s\n",
  2004             LARGE_FILE_NAME);
  2005         failed_already=1;
  2006         rv = -1;
  2007         goto done;
  2009 #endif
  2010     /*
  2011      * header for large file
  2012      */
  2013     large_file_header = PR_MALLOC(LARGE_FILE_HEADER_SIZE);
  2014     if (large_file_header == NULL) {
  2015         fprintf(stderr,"prsocket_test failed to malloc header file\n");
  2016         failed_already=1;
  2017         rv = -1;
  2018         goto done;
  2020     memset(large_file_header, (int) PR_IntervalNow(),
  2021         LARGE_FILE_HEADER_SIZE);
  2022     /*
  2023      * trailer for large file
  2024      */
  2025     large_file_trailer = PR_MALLOC(LARGE_FILE_TRAILER_SIZE);
  2026     if (large_file_trailer == NULL) {
  2027         fprintf(stderr,"prsocket_test failed to malloc header trailer\n");
  2028         failed_already=1;
  2029         rv = -1;
  2030         goto done;
  2032     memset(large_file_trailer, (int) PR_IntervalNow(),
  2033         LARGE_FILE_TRAILER_SIZE);
  2035     datalen = tcp_mesg_size;
  2036     thread_count = 0;
  2037     /*
  2038      * start the server thread
  2039      */
  2040     sparamp = PR_NEW(Server_Param);
  2041     if (sparamp == NULL) {
  2042         fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  2043         failed_already=1;
  2044         rv = -1;
  2045         goto done;
  2047     server_sem = PR_NewSem(0);
  2048     if (server_sem == NULL) {
  2049         fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
  2050         failed_already=1;
  2051         rv = -1;
  2052         goto done;
  2054     mon2 = PR_NewMonitor();
  2055     if (mon2 == NULL) {
  2056         fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
  2057         failed_already=1;
  2058         rv = -1;
  2059         goto done;
  2061     PR_EnterMonitor(mon2);
  2063     sparamp->addr_sem = server_sem;
  2064     sparamp->exit_mon = mon2;
  2065     sparamp->exit_counter = &thread_count;
  2066     sparamp->datalen = datalen;
  2067     t = PR_CreateThread(PR_USER_THREAD,
  2068         TransmitFile_Server, (void *)sparamp, 
  2069         PR_PRIORITY_NORMAL,
  2070         PR_LOCAL_THREAD,
  2071         PR_UNJOINABLE_THREAD,
  2072         0);
  2073     if (t == NULL) {
  2074         fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  2075         failed_already=1;
  2076         rv = -1;
  2077         goto done;
  2079     DPRINTF(("Created TCP server = 0x%x\n", t));
  2080     thread_count++;
  2082     /*
  2083      * wait till the server address is setup
  2084      */
  2085     PR_WaitSem(server_sem);
  2087     /*
  2088      * Now start a bunch of client threads
  2089      */
  2091     cparamp = PR_NEW(Client_Param);
  2092     if (cparamp == NULL) {
  2093         fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  2094         failed_already=1;
  2095         rv = -1;
  2096         goto done;
  2098     cparamp->server_addr = tcp_server_addr;
  2099     cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
  2100     cparamp->exit_mon = mon2;
  2101     cparamp->exit_counter = &thread_count;
  2102     cparamp->datalen = datalen;
  2103     for (i = 0; i < num_transmitfile_clients; i++) {
  2104         t = create_new_thread(PR_USER_THREAD,
  2105             TransmitFile_Client, (void *) cparamp,
  2106             PR_PRIORITY_NORMAL,
  2107             PR_LOCAL_THREAD,
  2108             PR_UNJOINABLE_THREAD,
  2109             0, i);
  2110         if (t == NULL) {
  2111             fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  2112             rv = -1;
  2113             failed_already=1;
  2114             goto done;
  2116         DPRINTF(("Created TransmitFile client = 0x%lx\n", t));
  2117         thread_count++;
  2119     /* Wait for server and client threads to exit */
  2120     while (thread_count) {
  2121         PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
  2122         DPRINTF(("Socket_Misc_Test - thread_count  = %d\n", thread_count));
  2124     PR_ExitMonitor(mon2);
  2125 done:
  2126     if (buf) {
  2127         PR_DELETE(buf);
  2129 #if defined(XP_UNIX) && !defined(SYMBIAN)
  2130     munmap((char*)small_file_addr, SMALL_FILE_SIZE);
  2131     munmap((char*)large_file_addr, LARGE_FILE_SIZE);
  2132 #endif
  2133     PR_Close(small_file_fd);
  2134     PR_Close(large_file_fd);
  2135     if ((PR_Delete(SMALL_FILE_NAME)) == PR_FAILURE) {
  2136         fprintf(stderr,"prsocket_test: failed to unlink file %s\n",
  2137             SMALL_FILE_NAME);
  2138         failed_already=1;
  2140     if ((PR_Delete(LARGE_FILE_NAME)) == PR_FAILURE) {
  2141         fprintf(stderr,"prsocket_test: failed to unlink file %s\n",
  2142             LARGE_FILE_NAME);
  2143         failed_already=1;
  2145     if ((PR_RmDir(TEST_DIR)) == PR_FAILURE) {
  2146         fprintf(stderr,"prsocket_test failed to rmdir %s: (%ld, %ld)\n",
  2147             TEST_DIR, PR_GetError(), PR_GetOSError());
  2148         failed_already=1;
  2151     printf("%-29s%s","Socket_Misc_Test",":");
  2152     printf("%2d Server %2d Clients\n",1, num_transmitfile_clients);
  2153     printf("%30s Sizes of Transmitted Files  - %4d KB, %2d MB \n",":",
  2154         SMALL_FILE_SIZE/1024, LARGE_FILE_SIZE/(1024 * 1024));
  2157     return rv;
  2159 /************************************************************************/
  2161 /*
  2162  * Test Socket NSPR APIs
  2163  */
  2165 int main(int argc, char **argv)
  2167     /*
  2168      * -d           debug mode
  2169      */
  2171     PLOptStatus os;
  2172     PLOptState *opt = PL_CreateOptState(argc, argv, "d");
  2173     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  2175         if (PL_OPT_BAD == os) continue;
  2176         switch (opt->option)
  2178         case 'd':  /* debug mode */
  2179             _debug_on = 1;
  2180             break;
  2181         default:
  2182             break;
  2185     PL_DestroyOptState(opt);
  2187     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  2188     PR_STDIO_INIT();
  2190     PR_SetConcurrency(4);
  2192     emuSendFileIdentity = PR_GetUniqueIdentity("Emulated SendFile");
  2193     emuSendFileMethods = *PR_GetDefaultIOMethods();
  2194     emuSendFileMethods.transmitfile = emu_TransmitFile;
  2195     emuSendFileMethods.sendfile = emu_SendFile;
  2197     /*
  2198      * run client-server test with TCP, Ipv4-Ipv4
  2199      */
  2200 	printf("TCP Client/Server Test - IPv4/Ipv4\n");
  2201     if (TCP_Socket_Client_Server_Test() < 0) {
  2202         printf("TCP_Socket_Client_Server_Test failed\n");
  2203         goto done;
  2204     } else
  2205         printf("TCP_Socket_Client_Server_Test Passed\n");
  2206     /*
  2207      * client-server test, Ipv6-Ipv4
  2208      */
  2209 	client_domain = PR_AF_INET6;
  2210 	printf("TCP Client/Server Test - IPv6/Ipv4\n");
  2211     if (TCP_Socket_Client_Server_Test() < 0) {
  2212         printf("TCP_Socket_Client_Server_Test failed\n");
  2213         goto done;
  2214     } else
  2215         printf("TCP_Socket_Client_Server_Test Passed\n");
  2216     /*
  2217      * client-server test, Ipv4-Ipv6
  2218      */
  2219 	client_domain = PR_AF_INET;
  2220 	server_domain = PR_AF_INET6;
  2221 	printf("TCP Client/Server Test - IPv4/Ipv6\n");
  2222     if (TCP_Socket_Client_Server_Test() < 0) {
  2223         printf("TCP_Socket_Client_Server_Test failed\n");
  2224         goto done;
  2225     } else
  2226         printf("TCP_Socket_Client_Server_Test Passed\n");
  2227     /*
  2228      * client-server test, Ipv6-Ipv6
  2229      */
  2230 	client_domain = PR_AF_INET6;
  2231 	server_domain = PR_AF_INET6;
  2232 	printf("TCP Client/Server Test - IPv6/Ipv6\n");
  2233     if (TCP_Socket_Client_Server_Test() < 0) {
  2234         printf("TCP_Socket_Client_Server_Test failed\n");
  2235         goto done;
  2236     } else
  2237         printf("TCP_Socket_Client_Server_Test Passed\n");
  2238 	test_cancelio = 0;
  2240 #if defined(SYMBIAN) && !defined(__WINSCW__)
  2241 	/* UDP tests only run on Symbian devices but not emulator */
  2242     /*
  2243      * run client-server test with UDP, IPv4/IPv4
  2244      */
  2245 	printf("UDP Client/Server Test - IPv4/Ipv4\n");
  2246 	client_domain = PR_AF_INET;
  2247 	server_domain = PR_AF_INET;
  2248     if (UDP_Socket_Client_Server_Test() < 0) {
  2249         printf("UDP_Socket_Client_Server_Test failed\n");
  2250         goto done;
  2251     } else
  2252         printf("UDP_Socket_Client_Server_Test Passed\n");
  2253     /*
  2254      * run client-server test with UDP, IPv6/IPv4
  2255      */
  2256 	printf("UDP Client/Server Test - IPv6/Ipv4\n");
  2257 	client_domain = PR_AF_INET6;
  2258 	server_domain = PR_AF_INET;
  2259     if (UDP_Socket_Client_Server_Test() < 0) {
  2260         printf("UDP_Socket_Client_Server_Test failed\n");
  2261         goto done;
  2262     } else
  2263         printf("UDP_Socket_Client_Server_Test Passed\n");
  2264     /*
  2265      * run client-server test with UDP,IPv4-IPv6
  2266      */
  2267 	printf("UDP Client/Server Test - IPv4/Ipv6\n");
  2268 	client_domain = PR_AF_INET;
  2269 	server_domain = PR_AF_INET6;
  2270     if (UDP_Socket_Client_Server_Test() < 0) {
  2271         printf("UDP_Socket_Client_Server_Test failed\n");
  2272         goto done;
  2273     } else
  2274         printf("UDP_Socket_Client_Server_Test Passed\n");
  2275     /*
  2276      * run client-server test with UDP,IPv6-IPv6
  2277      */
  2278 	printf("UDP Client/Server Test - IPv6/Ipv6\n");
  2279 	client_domain = PR_AF_INET6;
  2280 	server_domain = PR_AF_INET6;
  2281     if (UDP_Socket_Client_Server_Test() < 0) {
  2282         printf("UDP_Socket_Client_Server_Test failed\n");
  2283         goto done;
  2284     } else
  2285         printf("UDP_Socket_Client_Server_Test Passed\n");
  2286 #endif
  2288     /*
  2289      * Misc socket tests - including transmitfile, etc.
  2290      */
  2292     /* File transmission test can not be done in Symbian OS because of 
  2293      * large file's size and the incomplete mmap() implementation. */
  2294 #if !defined(WIN16) && !defined(SYMBIAN)
  2295     /*
  2296 ** The 'transmit file' test does not run because
  2297 ** transmit file is not implemented in NSPR yet.
  2298 **
  2299 */
  2300     if (Socket_Misc_Test() < 0) {
  2301         printf("Socket_Misc_Test failed\n");
  2302         failed_already=1;
  2303         goto done;
  2304     } else
  2305         printf("Socket_Misc_Test passed\n");
  2307     /*
  2308      * run client-server test with TCP again to test
  2309      * recycling used sockets from PR_TransmitFile().
  2310      */
  2311     if (TCP_Socket_Client_Server_Test() < 0) {
  2312         printf("TCP_Socket_Client_Server_Test failed\n");
  2313         goto done;
  2314     } else
  2315         printf("TCP_Socket_Client_Server_Test Passed\n");
  2316 #endif
  2318 done:
  2319     PR_Cleanup();
  2320     if (failed_already) return 1;
  2321     else return 0;

mercurial