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