nsprpub/pr/tests/socket.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial