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 +}