|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /*********************************************************************** |
|
7 ** |
|
8 ** Name: socket.c |
|
9 ** |
|
10 ** Description: Test socket functionality. |
|
11 ** |
|
12 ** Modification History: |
|
13 */ |
|
14 #include "primpl.h" |
|
15 |
|
16 #include "plgetopt.h" |
|
17 |
|
18 #include <stdio.h> |
|
19 #include <string.h> |
|
20 #include <errno.h> |
|
21 #ifdef XP_UNIX |
|
22 #include <sys/mman.h> |
|
23 #endif |
|
24 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) |
|
25 #include <pthread.h> |
|
26 #endif |
|
27 |
|
28 #ifdef WIN32 |
|
29 #include <process.h> |
|
30 #endif |
|
31 |
|
32 static int _debug_on = 0; |
|
33 static int test_cancelio = 0; |
|
34 |
|
35 #include "obsolete/prsem.h" |
|
36 |
|
37 #ifdef XP_PC |
|
38 #define mode_t int |
|
39 #endif |
|
40 |
|
41 #define DPRINTF(arg) if (_debug_on) printf arg |
|
42 |
|
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 */ |
|
65 |
|
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) |
|
77 |
|
78 #define BUF_DATA_SIZE (2 * 1024) |
|
79 #define TCP_MESG_SIZE 1024 |
|
80 /* |
|
81 * set UDP datagram size small enough that datagrams sent to a port on the |
|
82 * local host will not be lost |
|
83 */ |
|
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 |
|
87 |
|
88 #ifdef SYMBIAN |
|
89 #define NUM_TRANSMITFILE_CLIENTS 1 |
|
90 #else |
|
91 #define NUM_TRANSMITFILE_CLIENTS 4 |
|
92 #endif |
|
93 |
|
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 |
|
100 |
|
101 #ifdef WINCE |
|
102 #define perror(s) |
|
103 #endif |
|
104 |
|
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; |
|
113 |
|
114 static PRInt32 thread_count; |
|
115 PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET; |
|
116 |
|
117 /* an I/O layer that uses the emulated senfile method */ |
|
118 static PRDescIdentity emuSendFileIdentity; |
|
119 static PRIOMethods emuSendFileMethods; |
|
120 |
|
121 int failed_already=0; |
|
122 typedef struct buffer { |
|
123 char data[BUF_DATA_SIZE]; |
|
124 } buffer; |
|
125 |
|
126 PRNetAddr tcp_server_addr, udp_server_addr; |
|
127 |
|
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; |
|
132 |
|
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; |
|
139 |
|
140 |
|
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; |
|
148 |
|
149 /* the sendfile method in emuSendFileMethods */ |
|
150 static PRInt32 PR_CALLBACK |
|
151 emu_SendFile(PRFileDesc *sd, PRSendFileData *sfd, |
|
152 PRTransmitFileFlags flags, PRIntervalTime timeout) |
|
153 { |
|
154 return PR_EmulateSendFile(sd, sfd, flags, timeout); |
|
155 } |
|
156 |
|
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) |
|
161 { |
|
162 PRSendFileData sfd; |
|
163 |
|
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); |
|
172 } |
|
173 |
|
174 /* |
|
175 * readn |
|
176 * read data from sockfd into buf |
|
177 */ |
|
178 static PRInt32 |
|
179 readn(PRFileDesc *sockfd, char *buf, int len) |
|
180 { |
|
181 int rem; |
|
182 int bytes; |
|
183 int offset = 0; |
|
184 int err; |
|
185 PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; |
|
186 |
|
187 if (test_cancelio) |
|
188 timeout = PR_SecondsToInterval(2); |
|
189 |
|
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; |
|
207 } |
|
208 #endif |
|
209 return -1; |
|
210 } |
|
211 } |
|
212 return len; |
|
213 } |
|
214 |
|
215 /* |
|
216 * writen |
|
217 * write data from buf to sockfd |
|
218 */ |
|
219 static PRInt32 |
|
220 writen(PRFileDesc *sockfd, char *buf, int len) |
|
221 { |
|
222 int rem; |
|
223 int bytes; |
|
224 int offset = 0; |
|
225 |
|
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; |
|
235 } |
|
236 return len; |
|
237 } |
|
238 |
|
239 /* |
|
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 |
|
244 */ |
|
245 static void PR_CALLBACK |
|
246 Serve_Client(void *arg) |
|
247 { |
|
248 Serve_Client_Param *scp = (Serve_Client_Param *) arg; |
|
249 PRFileDesc *sockfd; |
|
250 buffer *in_buf; |
|
251 PRInt32 bytes, j; |
|
252 |
|
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; |
|
260 } |
|
261 |
|
262 |
|
263 for (j = 0; j < num_tcp_mesgs_per_connection; j++) { |
|
264 /* |
|
265 * Read data from client and send it back to the client unmodified |
|
266 */ |
|
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; |
|
271 } |
|
272 /* Shutdown only RCV will cause error on Symbian OS */ |
|
273 #if !defined(SYMBIAN) |
|
274 /* |
|
275 * shutdown reads, after the last read |
|
276 */ |
|
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"); |
|
280 } |
|
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; |
|
288 } |
|
289 } |
|
290 /* |
|
291 * shutdown reads and writes |
|
292 */ |
|
293 if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) { |
|
294 fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n"); |
|
295 failed_already=1; |
|
296 } |
|
297 |
|
298 exit: |
|
299 PR_Close(sockfd); |
|
300 if (in_buf) { |
|
301 PR_DELETE(in_buf); |
|
302 } |
|
303 } |
|
304 |
|
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) |
|
312 { |
|
313 PRInt32 native_thread = 0; |
|
314 |
|
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; |
|
333 } |
|
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; |
|
344 |
|
345 thandle = (HANDLE) _beginthreadex( |
|
346 NULL, |
|
347 stackSize, |
|
348 (unsigned (__stdcall *)(void *))start, |
|
349 arg, |
|
350 STACK_SIZE_PARAM_IS_A_RESERVATION, |
|
351 &tid); |
|
352 return((PRThread *) thandle); |
|
353 #endif |
|
354 } else { |
|
355 return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); |
|
356 } |
|
357 #else |
|
358 return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); |
|
359 #endif |
|
360 } |
|
361 |
|
362 /* |
|
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. |
|
367 */ |
|
368 static void PR_CALLBACK |
|
369 TCP_Server(void *arg) |
|
370 { |
|
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; |
|
377 /* |
|
378 * Create a tcp socket |
|
379 */ |
|
380 if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) { |
|
381 fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); |
|
382 goto exit; |
|
383 } |
|
384 memset(&netaddr, 0 , sizeof(netaddr)); |
|
385 |
|
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; |
|
390 } |
|
391 /* |
|
392 * try a few times to bind server's address, if addresses are in |
|
393 * use |
|
394 */ |
|
395 i = 0; |
|
396 |
|
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; |
|
402 } |
|
403 fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
|
404 perror("PR_Bind"); |
|
405 failed_already=1; |
|
406 goto exit; |
|
407 } |
|
408 |
|
409 if (PR_Listen(sockfd, 32) < 0) { |
|
410 fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); |
|
411 failed_already=1; |
|
412 goto exit; |
|
413 } |
|
414 |
|
415 if (PR_GetSockName(sockfd, &netaddr) < 0) { |
|
416 fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); |
|
417 failed_already=1; |
|
418 goto exit; |
|
419 } |
|
420 |
|
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; |
|
428 } |
|
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); |
|
432 |
|
433 /* |
|
434 * Wake up parent thread because server address is bound and made |
|
435 * available in the global variable 'tcp_server_addr' |
|
436 */ |
|
437 PR_PostSem(sp->addr_sem); |
|
438 |
|
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); |
|
442 |
|
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; |
|
448 } |
|
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; |
|
454 } |
|
455 |
|
456 /* |
|
457 * Start a Serve_Client thread for each incoming connection |
|
458 */ |
|
459 scp->sockfd = newsockfd; |
|
460 scp->datalen = sp->datalen; |
|
461 |
|
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; |
|
472 } |
|
473 DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t)); |
|
474 } |
|
475 |
|
476 exit: |
|
477 if (sockfd) { |
|
478 PR_Close(sockfd); |
|
479 } |
|
480 |
|
481 /* |
|
482 * Decrement exit_counter and notify parent thread |
|
483 */ |
|
484 |
|
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())); |
|
490 } |
|
491 |
|
492 /* |
|
493 * UDP Server |
|
494 * Server Thread |
|
495 * Bind an address to a socket, read data from clients and send data |
|
496 * back to clients |
|
497 */ |
|
498 static void PR_CALLBACK |
|
499 UDP_Server(void *arg) |
|
500 { |
|
501 Server_Param *sp = (Server_Param *) arg; |
|
502 PRFileDesc *sockfd; |
|
503 buffer *in_buf; |
|
504 PRNetAddr netaddr; |
|
505 PRInt32 bytes, i, rv = 0; |
|
506 |
|
507 |
|
508 bytes = sp->datalen; |
|
509 /* |
|
510 * Create a udp socket |
|
511 */ |
|
512 if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) { |
|
513 fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n"); |
|
514 failed_already=1; |
|
515 return; |
|
516 } |
|
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; |
|
523 } |
|
524 /* |
|
525 * try a few times to bind server's address, if addresses are in |
|
526 * use |
|
527 */ |
|
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; |
|
534 } |
|
535 fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
|
536 perror("PR_Bind"); |
|
537 failed_already=1; |
|
538 return; |
|
539 } |
|
540 |
|
541 if (PR_GetSockName(sockfd, &netaddr) < 0) { |
|
542 fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); |
|
543 failed_already=1; |
|
544 return; |
|
545 } |
|
546 |
|
547 DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", |
|
548 netaddr.inet.ip, netaddr.inet.port)); |
|
549 /* |
|
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). |
|
553 */ |
|
554 |
|
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; |
|
561 } |
|
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); |
|
565 |
|
566 /* |
|
567 * Wake up parent thread because server address is bound and made |
|
568 * available in the global variable 'udp_server_addr' |
|
569 */ |
|
570 PR_PostSem(sp->addr_sem); |
|
571 |
|
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; |
|
578 } |
|
579 /* |
|
580 * Receive datagrams from clients and send them back, unmodified, to the |
|
581 * clients |
|
582 */ |
|
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])); |
|
588 |
|
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; |
|
596 } |
|
597 rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr, |
|
598 PR_INTERVAL_NO_TIMEOUT); |
|
599 if (rv != bytes) { |
|
600 return; |
|
601 } |
|
602 } |
|
603 |
|
604 PR_DELETE(in_buf); |
|
605 PR_Close(sockfd); |
|
606 |
|
607 /* |
|
608 * Decrement exit_counter and notify parent thread |
|
609 */ |
|
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())); |
|
615 } |
|
616 |
|
617 /* |
|
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 |
|
624 */ |
|
625 static void PR_CALLBACK |
|
626 TCP_Client(void *arg) |
|
627 { |
|
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; |
|
633 |
|
634 |
|
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; |
|
641 } |
|
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; |
|
647 } |
|
648 netaddr = cp->server_addr; |
|
649 |
|
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; |
|
655 } |
|
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; |
|
661 } |
|
662 for (j = 0; j < num_tcp_mesgs_per_connection; j++) { |
|
663 /* |
|
664 * fill in random data |
|
665 */ |
|
666 memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes); |
|
667 /* |
|
668 * write to server |
|
669 */ |
|
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; |
|
678 } |
|
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; |
|
685 } |
|
686 /* |
|
687 * verify the data read |
|
688 */ |
|
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; |
|
693 } |
|
694 } |
|
695 /* |
|
696 * shutdown reads and writes |
|
697 */ |
|
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; |
|
704 } |
|
705 PR_Close(sockfd); |
|
706 } |
|
707 |
|
708 PR_DELETE(out_buf); |
|
709 PR_DELETE(in_buf); |
|
710 |
|
711 /* |
|
712 * Decrement exit_counter and notify parent thread |
|
713 */ |
|
714 |
|
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())); |
|
720 } |
|
721 |
|
722 /* |
|
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 |
|
730 */ |
|
731 static void PR_CALLBACK |
|
732 UDP_Client(void *arg) |
|
733 { |
|
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; |
|
739 |
|
740 |
|
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; |
|
747 } |
|
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; |
|
753 } |
|
754 if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) { |
|
755 fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n"); |
|
756 failed_already=1; |
|
757 return; |
|
758 } |
|
759 |
|
760 /* |
|
761 * bind an address for the client, let the system chose the port |
|
762 * number |
|
763 */ |
|
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; |
|
770 } |
|
771 if (PR_Bind(sockfd, &netaddr) < 0) { |
|
772 fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
|
773 perror("PR_Bind"); |
|
774 return; |
|
775 } |
|
776 |
|
777 if (PR_GetSockName(sockfd, &netaddr) < 0) { |
|
778 fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); |
|
779 failed_already=1; |
|
780 return; |
|
781 } |
|
782 |
|
783 DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", |
|
784 netaddr.inet.ip, netaddr.inet.port)); |
|
785 |
|
786 netaddr = cp->server_addr; |
|
787 |
|
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; |
|
793 } |
|
794 } |
|
795 |
|
796 for (i = 0; i < num_udp_datagrams_per_client; i++) { |
|
797 /* |
|
798 * fill in random data |
|
799 */ |
|
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); |
|
803 /* |
|
804 * write to server |
|
805 */ |
|
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; |
|
814 } |
|
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; |
|
825 } |
|
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)))); |
|
828 /* |
|
829 * verify the data read |
|
830 */ |
|
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; |
|
835 } |
|
836 } |
|
837 PR_Close(sockfd); |
|
838 |
|
839 PR_DELETE(in_buf); |
|
840 PR_DELETE(out_buf); |
|
841 |
|
842 /* |
|
843 * Decrement exit_counter and notify parent thread |
|
844 */ |
|
845 |
|
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())); |
|
852 } |
|
853 |
|
854 /* |
|
855 * TCP_Socket_Client_Server_Test - concurrent server test |
|
856 * |
|
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. |
|
863 * |
|
864 */ |
|
865 |
|
866 static PRInt32 |
|
867 TCP_Socket_Client_Server_Test(void) |
|
868 { |
|
869 int i; |
|
870 PRThread *t; |
|
871 PRSemaphore *server_sem; |
|
872 Server_Param *sparamp; |
|
873 Client_Param *cparamp; |
|
874 PRMonitor *mon2; |
|
875 PRInt32 datalen; |
|
876 |
|
877 |
|
878 datalen = tcp_mesg_size; |
|
879 thread_count = 0; |
|
880 /* |
|
881 * start the server thread |
|
882 */ |
|
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; |
|
888 } |
|
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; |
|
894 } |
|
895 mon2 = PR_NewMonitor(); |
|
896 if (mon2 == NULL) { |
|
897 fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); |
|
898 failed_already=1; |
|
899 return -1; |
|
900 } |
|
901 PR_EnterMonitor(mon2); |
|
902 |
|
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, |
|
912 0); |
|
913 if (t == NULL) { |
|
914 fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
|
915 failed_already=1; |
|
916 return -1; |
|
917 } |
|
918 DPRINTF(("Created TCP server = 0x%lx\n", t)); |
|
919 thread_count++; |
|
920 |
|
921 /* |
|
922 * wait till the server address is setup |
|
923 */ |
|
924 PR_WaitSem(server_sem); |
|
925 |
|
926 /* |
|
927 * Now start a bunch of client threads |
|
928 */ |
|
929 |
|
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; |
|
935 } |
|
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; |
|
951 } |
|
952 DPRINTF(("Created TCP client = 0x%lx\n", t)); |
|
953 thread_count++; |
|
954 } |
|
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)); |
|
959 } |
|
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); |
|
966 |
|
967 return 0; |
|
968 } |
|
969 |
|
970 /* |
|
971 * UDP_Socket_Client_Server_Test - iterative server test |
|
972 * |
|
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. |
|
979 * |
|
980 */ |
|
981 |
|
982 static PRInt32 |
|
983 UDP_Socket_Client_Server_Test(void) |
|
984 { |
|
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; |
|
993 |
|
994 |
|
995 datalen = udp_datagram_size; |
|
996 thread_count = 0; |
|
997 /* |
|
998 * start the server thread |
|
999 */ |
|
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; |
|
1005 } |
|
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; |
|
1011 } |
|
1012 mon2 = PR_NewMonitor(); |
|
1013 if (mon2 == NULL) { |
|
1014 fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); |
|
1015 failed_already=1; |
|
1016 return -1; |
|
1017 } |
|
1018 PR_EnterMonitor(mon2); |
|
1019 |
|
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, |
|
1030 0); |
|
1031 if (t == NULL) { |
|
1032 fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
|
1033 failed_already=1; |
|
1034 return -1; |
|
1035 } |
|
1036 thread_count++; |
|
1037 |
|
1038 /* |
|
1039 * wait till the server address is setup |
|
1040 */ |
|
1041 PR_WaitSem(server_sem); |
|
1042 |
|
1043 /* |
|
1044 * Now start a bunch of client threads |
|
1045 */ |
|
1046 |
|
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; |
|
1053 } |
|
1054 cparamp->server_addr = udp_server_addr; |
|
1055 cparamp->exit_mon = mon2; |
|
1056 cparamp->exit_counter = &thread_count; |
|
1057 cparamp->datalen = datalen; |
|
1058 /* |
|
1059 * Cause every other client thread to connect udp sockets |
|
1060 */ |
|
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, |
|
1072 0); |
|
1073 if (t == NULL) { |
|
1074 fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
|
1075 failed_already=1; |
|
1076 return -1; |
|
1077 } |
|
1078 thread_count++; |
|
1079 } |
|
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)); |
|
1084 } |
|
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); |
|
1090 |
|
1091 return 0; |
|
1092 } |
|
1093 |
|
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; |
|
1097 /* |
|
1098 * TransmitFile_Client |
|
1099 * Client Thread |
|
1100 */ |
|
1101 static void |
|
1102 TransmitFile_Client(void *arg) |
|
1103 { |
|
1104 PRFileDesc *sockfd; |
|
1105 union PRNetAddr netaddr; |
|
1106 char *small_buf, *large_buf; |
|
1107 Client_Param *cp = (Client_Param *) arg; |
|
1108 PRInt32 rlen; |
|
1109 |
|
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; |
|
1116 } |
|
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; |
|
1123 } |
|
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; |
|
1127 |
|
1128 if ((sockfd = PR_NewTCPSocket()) == NULL) { |
|
1129 fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); |
|
1130 failed_already=1; |
|
1131 return; |
|
1132 } |
|
1133 |
|
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; |
|
1138 } |
|
1139 /* |
|
1140 * read the small file and verify the data |
|
1141 */ |
|
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; |
|
1148 } |
|
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; |
|
1156 } |
|
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; |
|
1163 } |
|
1164 #endif |
|
1165 /* |
|
1166 * read the large file and verify the data |
|
1167 */ |
|
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; |
|
1173 } |
|
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; |
|
1179 } |
|
1180 #endif |
|
1181 |
|
1182 |
|
1183 /* |
|
1184 * receive data from PR_SendFile |
|
1185 */ |
|
1186 /* |
|
1187 * case 1: small file with header and trailer |
|
1188 */ |
|
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; |
|
1196 } |
|
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; |
|
1203 } |
|
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; |
|
1210 } |
|
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; |
|
1218 } |
|
1219 #endif |
|
1220 /* |
|
1221 * case 2: partial large file at zero offset, file with header and trailer |
|
1222 */ |
|
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; |
|
1230 } |
|
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; |
|
1237 } |
|
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; |
|
1244 } |
|
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; |
|
1252 } |
|
1253 #endif |
|
1254 /* |
|
1255 * case 3: partial small file at non-zero offset, with header |
|
1256 */ |
|
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; |
|
1263 } |
|
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; |
|
1270 } |
|
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; |
|
1277 } |
|
1278 #endif |
|
1279 /* |
|
1280 * case 4: partial small file at non-zero offset, with trailer |
|
1281 */ |
|
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; |
|
1288 } |
|
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; |
|
1296 } |
|
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; |
|
1303 } |
|
1304 #endif |
|
1305 /* |
|
1306 * case 5: partial large file at non-zero offset, file with header |
|
1307 */ |
|
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; |
|
1314 } |
|
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; |
|
1321 } |
|
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; |
|
1329 } |
|
1330 #endif |
|
1331 /* |
|
1332 * case 6: partial small file at non-zero offset, with header |
|
1333 */ |
|
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; |
|
1340 } |
|
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; |
|
1346 } |
|
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; |
|
1352 |
|
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))); |
|
1361 } |
|
1362 #endif |
|
1363 fprintf(stderr, |
|
1364 "SendFile 6. ERROR - small file data corruption\n"); |
|
1365 failed_already=1; |
|
1366 return; |
|
1367 } |
|
1368 #endif |
|
1369 /* |
|
1370 * case 7: partial large file at non-zero offset, with header |
|
1371 */ |
|
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; |
|
1378 } |
|
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; |
|
1385 } |
|
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; |
|
1393 } |
|
1394 #endif |
|
1395 /* |
|
1396 * case 8: partial large file at non-zero, page-aligned offset, with |
|
1397 * header and trailer |
|
1398 */ |
|
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; |
|
1406 } |
|
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; |
|
1413 } |
|
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; |
|
1421 } |
|
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; |
|
1429 } |
|
1430 #endif |
|
1431 PR_DELETE(small_buf); |
|
1432 PR_DELETE(large_buf); |
|
1433 PR_Close(sockfd); |
|
1434 |
|
1435 |
|
1436 /* |
|
1437 * Decrement exit_counter and notify parent thread |
|
1438 */ |
|
1439 |
|
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())); |
|
1445 } |
|
1446 |
|
1447 /* |
|
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 |
|
1452 */ |
|
1453 static void |
|
1454 Serve_TransmitFile_Client(void *arg) |
|
1455 { |
|
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; |
|
1463 |
|
1464 sockfd = scp->sockfd; |
|
1465 local_small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDONLY,0); |
|
1466 |
|
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; |
|
1472 } |
|
1473 local_large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDONLY,0); |
|
1474 |
|
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; |
|
1480 } |
|
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; |
|
1489 } |
|
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; |
|
1497 } |
|
1498 |
|
1499 /* |
|
1500 * PR_SendFile test cases |
|
1501 */ |
|
1502 |
|
1503 /* |
|
1504 * case 1: small file with header and trailer |
|
1505 */ |
|
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; |
|
1525 } |
|
1526 |
|
1527 /* |
|
1528 * case 2: partial large file at zero offset, file with header and trailer |
|
1529 */ |
|
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; |
|
1549 } |
|
1550 /* |
|
1551 * case 3: partial small file at non-zero offset, with header |
|
1552 */ |
|
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; |
|
1571 } |
|
1572 /* |
|
1573 * case 4: partial small file at non-zero offset, with trailer |
|
1574 */ |
|
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; |
|
1593 } |
|
1594 /* |
|
1595 * case 5: partial large file at non-zero offset, file with header |
|
1596 */ |
|
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; |
|
1615 } |
|
1616 /* |
|
1617 * case 6: partial small file from non-zero offset till end of file, with header |
|
1618 */ |
|
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; |
|
1637 } |
|
1638 /* |
|
1639 * case 7: partial large file at non-zero offset till end-of-file, with header |
|
1640 */ |
|
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; |
|
1659 } |
|
1660 /* |
|
1661 * case 8: partial large file at non-zero page-aligned offset, |
|
1662 * with header and trailer |
|
1663 */ |
|
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; |
|
1683 } |
|
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); |
|
1689 } |
|
1690 |
|
1691 /* |
|
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 |
|
1696 */ |
|
1697 static void |
|
1698 TransmitFile_Server(void *arg) |
|
1699 { |
|
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; |
|
1706 |
|
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; |
|
1712 } |
|
1713 /* |
|
1714 * Create a tcp socket |
|
1715 */ |
|
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; |
|
1720 } |
|
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); |
|
1725 /* |
|
1726 * try a few times to bind server's address, if addresses are in |
|
1727 * use |
|
1728 */ |
|
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; |
|
1735 } |
|
1736 fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
|
1737 failed_already=1; |
|
1738 perror("PR_Bind"); |
|
1739 goto exit; |
|
1740 } |
|
1741 |
|
1742 if (PR_Listen(sockfd, 32) < 0) { |
|
1743 fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); |
|
1744 failed_already=1; |
|
1745 goto exit; |
|
1746 } |
|
1747 |
|
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; |
|
1753 } |
|
1754 |
|
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; |
|
1760 |
|
1761 /* |
|
1762 * Wake up parent thread because server address is bound and made |
|
1763 * available in the global variable 'tcp_server_addr' |
|
1764 */ |
|
1765 PR_PostSem(sp->addr_sem); |
|
1766 |
|
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); |
|
1770 |
|
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; |
|
1777 } |
|
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; |
|
1787 } |
|
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; |
|
1794 } |
|
1795 } |
|
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; |
|
1801 } |
|
1802 |
|
1803 /* |
|
1804 * Start a Serve_Client thread for each incoming connection |
|
1805 */ |
|
1806 scp->sockfd = newsockfd; |
|
1807 scp->datalen = sp->datalen; |
|
1808 |
|
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, |
|
1814 0); |
|
1815 if (t[i] == NULL) { |
|
1816 fprintf(stderr, |
|
1817 "prsocket_test: PR_CreateThread failed\n"); |
|
1818 failed_already=1; |
|
1819 goto exit; |
|
1820 } |
|
1821 DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t)); |
|
1822 } |
|
1823 |
|
1824 /* |
|
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. |
|
1827 */ |
|
1828 |
|
1829 for (i = 0; i < num_transmitfile_clients; i++) { |
|
1830 PR_JoinThread(t[i]); |
|
1831 } |
|
1832 |
|
1833 exit: |
|
1834 if (t) { |
|
1835 PR_DELETE(t); |
|
1836 } |
|
1837 if (sockfd) { |
|
1838 PR_Close(sockfd); |
|
1839 } |
|
1840 |
|
1841 /* |
|
1842 * Decrement exit_counter and notify parent thread |
|
1843 */ |
|
1844 |
|
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())); |
|
1850 } |
|
1851 |
|
1852 /* |
|
1853 * Socket_Misc_Test - test miscellaneous functions |
|
1854 * |
|
1855 */ |
|
1856 static PRInt32 |
|
1857 Socket_Misc_Test(void) |
|
1858 { |
|
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; |
|
1866 |
|
1867 /* |
|
1868 * We deliberately pick a buffer size that is not a nice multiple |
|
1869 * of 1024. |
|
1870 */ |
|
1871 #define TRANSMITFILE_BUF_SIZE (4 * 1024 - 11) |
|
1872 |
|
1873 typedef struct { |
|
1874 char data[TRANSMITFILE_BUF_SIZE]; |
|
1875 } file_buf; |
|
1876 file_buf *buf = NULL; |
|
1877 |
|
1878 /* |
|
1879 * create file(s) to be transmitted |
|
1880 */ |
|
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; |
|
1885 } |
|
1886 |
|
1887 small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); |
|
1888 |
|
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; |
|
1895 } |
|
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; |
|
1902 } |
|
1903 /* |
|
1904 * fill in random data |
|
1905 */ |
|
1906 for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { |
|
1907 buf->data[i] = i; |
|
1908 } |
|
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; |
|
1921 } |
|
1922 count += bytes; |
|
1923 } while (count < SMALL_FILE_SIZE); |
|
1924 #ifdef XP_UNIX |
|
1925 /* |
|
1926 * map the small file; used in checking for data corruption |
|
1927 */ |
|
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; |
|
1936 } |
|
1937 #endif |
|
1938 /* |
|
1939 * header for small file |
|
1940 */ |
|
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; |
|
1947 } |
|
1948 memset(small_file_header, (int) PR_IntervalNow(), |
|
1949 SMALL_FILE_HEADER_SIZE); |
|
1950 /* |
|
1951 * trailer for small file |
|
1952 */ |
|
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; |
|
1959 } |
|
1960 memset(small_file_trailer, (int) PR_IntervalNow(), |
|
1961 SMALL_FILE_TRAILER_SIZE); |
|
1962 /* |
|
1963 * setup large file |
|
1964 */ |
|
1965 large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); |
|
1966 |
|
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; |
|
1973 } |
|
1974 /* |
|
1975 * fill in random data |
|
1976 */ |
|
1977 for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { |
|
1978 buf->data[i] = i; |
|
1979 } |
|
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; |
|
1993 } |
|
1994 count += bytes; |
|
1995 } while (count < LARGE_FILE_SIZE); |
|
1996 #if defined(XP_UNIX) && !defined(SYMBIAN) |
|
1997 /* |
|
1998 * map the large file; used in checking for data corruption |
|
1999 */ |
|
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; |
|
2008 } |
|
2009 #endif |
|
2010 /* |
|
2011 * header for large file |
|
2012 */ |
|
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; |
|
2019 } |
|
2020 memset(large_file_header, (int) PR_IntervalNow(), |
|
2021 LARGE_FILE_HEADER_SIZE); |
|
2022 /* |
|
2023 * trailer for large file |
|
2024 */ |
|
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; |
|
2031 } |
|
2032 memset(large_file_trailer, (int) PR_IntervalNow(), |
|
2033 LARGE_FILE_TRAILER_SIZE); |
|
2034 |
|
2035 datalen = tcp_mesg_size; |
|
2036 thread_count = 0; |
|
2037 /* |
|
2038 * start the server thread |
|
2039 */ |
|
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; |
|
2046 } |
|
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; |
|
2053 } |
|
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; |
|
2060 } |
|
2061 PR_EnterMonitor(mon2); |
|
2062 |
|
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, |
|
2072 0); |
|
2073 if (t == NULL) { |
|
2074 fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
|
2075 failed_already=1; |
|
2076 rv = -1; |
|
2077 goto done; |
|
2078 } |
|
2079 DPRINTF(("Created TCP server = 0x%x\n", t)); |
|
2080 thread_count++; |
|
2081 |
|
2082 /* |
|
2083 * wait till the server address is setup |
|
2084 */ |
|
2085 PR_WaitSem(server_sem); |
|
2086 |
|
2087 /* |
|
2088 * Now start a bunch of client threads |
|
2089 */ |
|
2090 |
|
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; |
|
2097 } |
|
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; |
|
2115 } |
|
2116 DPRINTF(("Created TransmitFile client = 0x%lx\n", t)); |
|
2117 thread_count++; |
|
2118 } |
|
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)); |
|
2123 } |
|
2124 PR_ExitMonitor(mon2); |
|
2125 done: |
|
2126 if (buf) { |
|
2127 PR_DELETE(buf); |
|
2128 } |
|
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; |
|
2139 } |
|
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; |
|
2144 } |
|
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; |
|
2149 } |
|
2150 |
|
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)); |
|
2155 |
|
2156 |
|
2157 return rv; |
|
2158 } |
|
2159 /************************************************************************/ |
|
2160 |
|
2161 /* |
|
2162 * Test Socket NSPR APIs |
|
2163 */ |
|
2164 |
|
2165 int main(int argc, char **argv) |
|
2166 { |
|
2167 /* |
|
2168 * -d debug mode |
|
2169 */ |
|
2170 |
|
2171 PLOptStatus os; |
|
2172 PLOptState *opt = PL_CreateOptState(argc, argv, "d"); |
|
2173 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) |
|
2174 { |
|
2175 if (PL_OPT_BAD == os) continue; |
|
2176 switch (opt->option) |
|
2177 { |
|
2178 case 'd': /* debug mode */ |
|
2179 _debug_on = 1; |
|
2180 break; |
|
2181 default: |
|
2182 break; |
|
2183 } |
|
2184 } |
|
2185 PL_DestroyOptState(opt); |
|
2186 |
|
2187 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); |
|
2188 PR_STDIO_INIT(); |
|
2189 |
|
2190 PR_SetConcurrency(4); |
|
2191 |
|
2192 emuSendFileIdentity = PR_GetUniqueIdentity("Emulated SendFile"); |
|
2193 emuSendFileMethods = *PR_GetDefaultIOMethods(); |
|
2194 emuSendFileMethods.transmitfile = emu_TransmitFile; |
|
2195 emuSendFileMethods.sendfile = emu_SendFile; |
|
2196 |
|
2197 /* |
|
2198 * run client-server test with TCP, Ipv4-Ipv4 |
|
2199 */ |
|
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"); |
|
2206 /* |
|
2207 * client-server test, Ipv6-Ipv4 |
|
2208 */ |
|
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"); |
|
2216 /* |
|
2217 * client-server test, Ipv4-Ipv6 |
|
2218 */ |
|
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"); |
|
2227 /* |
|
2228 * client-server test, Ipv6-Ipv6 |
|
2229 */ |
|
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; |
|
2239 |
|
2240 #if defined(SYMBIAN) && !defined(__WINSCW__) |
|
2241 /* UDP tests only run on Symbian devices but not emulator */ |
|
2242 /* |
|
2243 * run client-server test with UDP, IPv4/IPv4 |
|
2244 */ |
|
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"); |
|
2253 /* |
|
2254 * run client-server test with UDP, IPv6/IPv4 |
|
2255 */ |
|
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"); |
|
2264 /* |
|
2265 * run client-server test with UDP,IPv4-IPv6 |
|
2266 */ |
|
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"); |
|
2275 /* |
|
2276 * run client-server test with UDP,IPv6-IPv6 |
|
2277 */ |
|
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 |
|
2287 |
|
2288 /* |
|
2289 * Misc socket tests - including transmitfile, etc. |
|
2290 */ |
|
2291 |
|
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) |
|
2295 /* |
|
2296 ** The 'transmit file' test does not run because |
|
2297 ** transmit file is not implemented in NSPR yet. |
|
2298 ** |
|
2299 */ |
|
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"); |
|
2306 |
|
2307 /* |
|
2308 * run client-server test with TCP again to test |
|
2309 * recycling used sockets from PR_TransmitFile(). |
|
2310 */ |
|
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 |
|
2317 |
|
2318 done: |
|
2319 PR_Cleanup(); |
|
2320 if (failed_already) return 1; |
|
2321 else return 0; |
|
2322 } |