VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/socket.c@ 25803

Last change on this file since 25803 was 1, checked in by vboxsync, 55 years ago

import

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette