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