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