VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/udpsrv.c@ 99775

最後變更 在這個檔案從99775是 1,由 vboxsync 提交於 55 年 前

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 17.2 KB
 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/*******************************************************************
39** udpsrc.c -- Test basic function of UDP server
40**
41** udpsrv operates on the same machine with program udpclt.
42** udpsrv is the server side of a udp sockets application.
43** udpclt is the client side of a udp sockets application.
44**
45** The test is designed to assist developers in porting/debugging
46** the UDP socket functions of NSPR.
47**
48** This test is not a stress test.
49**
50** main() starts two threads: UDP_Server() and UDP_Client();
51** main() uses PR_JoinThread() to wait for the threads to complete.
52**
53** UDP_Server() does repeated recvfrom()s from a socket.
54** He detects an EOF condition set by UDP_Client(). For each
55** packet received by UDP_Server(), he checks its content for
56** expected content, then sends the packet back to UDP_Client().
57**
58** UDP_Client() sends packets to UDP_Server() using sendto()
59** he recieves packets back from the server via recvfrom().
60** After he sends enough packets containing UDP_AMOUNT_TO_WRITE
61** bytes of data, he sends an EOF message.
62**
63** The test issues a pass/fail message at end.
64**
65** Notes:
66** The variable "_debug_on" can be set to 1 to cause diagnostic
67** messages related to client/server synchronization. Useful when
68** the test hangs.
69**
70** Error messages are written to stdout.
71**
72********************************************************************
73*/
74/* --- include files --- */
75#include "nspr.h"
76#include "prpriv.h"
77
78#include "plgetopt.h"
79#include "prttools.h"
80
81#include <stdio.h>
82#include <stdlib.h>
83#include <string.h>
84#include <errno.h>
85
86#ifdef XP_PC
87#define mode_t int
88#endif
89
90#define UDP_BUF_SIZE 4096
91#define UDP_DGRAM_SIZE 128
92#define UDP_AMOUNT_TO_WRITE (PRInt32)((UDP_DGRAM_SIZE * 1000l) +1)
93#define NUM_UDP_CLIENTS 1
94#define NUM_UDP_DATAGRAMS_PER_CLIENT 5
95#define UDP_SERVER_PORT 9050
96#define UDP_CLIENT_PORT 9053
97#define MY_INADDR PR_INADDR_ANY
98#define PEER_INADDR PR_INADDR_LOOPBACK
99
100#define UDP_TIMEOUT 400000
101/* #define UDP_TIMEOUT PR_INTERVAL_NO_TIMEOUT */
102
103/* --- static data --- */
104static PRIntn _debug_on = 0;
105static PRBool passed = PR_TRUE;
106static PRUint32 cltBytesRead = 0;
107static PRUint32 srvBytesRead = 0;
108static PRFileDesc *output = NULL;
109
110/* --- static function declarations --- */
111#define DPRINTF(arg) if (_debug_on) PR_fprintf(output, arg)
112
113
114
115/*******************************************************************
116** ListNetAddr() -- Display the Net Address on stdout
117**
118** Description: displays the component parts of a PRNetAddr struct
119**
120** Arguments: address of PRNetAddr structure to display
121**
122** Returns: void
123**
124** Notes:
125**
126********************************************************************
127*/
128void ListNetAddr( char *msg, PRNetAddr *na )
129{
130 char mbuf[256];
131
132 sprintf( mbuf, "ListNetAddr: %s family: %d, port: %d, ip: %8.8X\n",
133 msg, na->inet.family, PR_ntohs( na->inet.port), PR_ntohl(na->inet.ip) );
134#if 0
135 DPRINTF( mbuf );
136#endif
137} /* --- end ListNetAddr() --- */
138
139/********************************************************************
140** UDP_Server() -- Test a UDP server application
141**
142** Description: The Server side of a UDP Client/Server application.
143**
144** Arguments: none
145**
146** Returns: void
147**
148** Notes:
149**
150**
151********************************************************************
152*/
153static void PR_CALLBACK UDP_Server( void *arg )
154{
155 static char svrBuf[UDP_BUF_SIZE];
156 PRFileDesc *svrSock;
157 PRInt32 rv;
158 PRNetAddr netaddr;
159 PRBool bound = PR_FALSE;
160 PRBool endOfInput = PR_FALSE;
161 PRInt32 numBytes = UDP_DGRAM_SIZE;
162
163 DPRINTF("udpsrv: UDP_Server(): starting\n" );
164
165 /* --- Create the socket --- */
166 DPRINTF("udpsrv: UDP_Server(): Creating UDP Socket\n" );
167 svrSock = PR_NewUDPSocket();
168 if ( svrSock == NULL )
169 {
170 passed = PR_FALSE;
171 if (debug_mode)
172 PR_fprintf(output,
173 "udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
174 return;
175 }
176
177 /* --- Initialize the sockaddr_in structure --- */
178 memset( &netaddr, 0, sizeof( netaddr ));
179 netaddr.inet.family = PR_AF_INET;
180 netaddr.inet.port = PR_htons( UDP_SERVER_PORT );
181 netaddr.inet.ip = PR_htonl( MY_INADDR );
182
183 /* --- Bind the socket --- */
184 while ( !bound )
185 {
186 DPRINTF("udpsrv: UDP_Server(): Binding socket\n" );
187 rv = PR_Bind( svrSock, &netaddr );
188 if ( rv < 0 )
189 {
190 if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
191 {
192 if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
193 PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
194 PR_Sleep( PR_MillisecondsToInterval( 2000 ));
195 continue;
196 }
197 else
198 {
199 passed = PR_FALSE;
200 if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
201 PR_Bind(): failed: %ld with error: %ld\n",
202 rv, PR_GetError() );
203 PR_Close( svrSock );
204 return;
205 }
206 }
207 else
208 bound = PR_TRUE;
209 }
210 ListNetAddr( "UDP_Server: after bind", &netaddr );
211
212 /* --- Recv the socket --- */
213 while( !endOfInput )
214 {
215 DPRINTF("udpsrv: UDP_Server(): RecvFrom() socket\n" );
216 rv = PR_RecvFrom( svrSock, svrBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
217 if ( rv == -1 )
218 {
219 passed = PR_FALSE;
220 if (debug_mode)
221 PR_fprintf(output,
222 "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
223 PR_GetError() );
224 PR_Close( svrSock );
225 return;
226 }
227 ListNetAddr( "UDP_Server after RecvFrom", &netaddr );
228
229 srvBytesRead += rv;
230
231 if ( svrBuf[0] == 'E' )
232 {
233 DPRINTF("udpsrv: UDP_Server(): EOF on input detected\n" );
234 endOfInput = PR_TRUE;
235 }
236
237 /* --- Send the socket --- */
238 DPRINTF("udpsrv: UDP_Server(): SendTo(): socket\n" );
239 rv = PR_SendTo( svrSock, svrBuf, rv, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT );
240 if ( rv == -1 )
241 {
242 passed = PR_FALSE;
243 if (debug_mode)
244 PR_fprintf(output,
245 "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
246 PR_GetError() );
247 PR_Close( svrSock );
248 return;
249 }
250 ListNetAddr( "UDP_Server after SendTo", &netaddr );
251 }
252
253 /* --- Close the socket --- */
254 DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
255 rv = PR_Close( svrSock );
256 if ( rv != PR_SUCCESS )
257 {
258 passed = PR_FALSE;
259 if (debug_mode)
260 PR_fprintf(output,
261 "udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
262 return;
263 }
264
265 DPRINTF("udpsrv: UDP_Server(): Normal end\n" );
266} /* --- end UDP_Server() --- */
267
268
269static char cltBuf[UDP_BUF_SIZE];
270static char cltBufin[UDP_BUF_SIZE];
271/********************************************************************
272** UDP_Client() -- Test a UDP client application
273**
274** Description:
275**
276** Arguments:
277**
278**
279** Returns:
280** 0 -- Successful execution
281** 1 -- Test failed.
282**
283** Notes:
284**
285**
286********************************************************************
287*/
288static void PR_CALLBACK UDP_Client( void *arg )
289{
290 PRFileDesc *cltSock;
291 PRInt32 rv;
292 PRBool bound = PR_FALSE;
293 PRNetAddr netaddr;
294 PRNetAddr netaddrx;
295 PRBool endOfInput = PR_FALSE;
296 PRInt32 numBytes = UDP_DGRAM_SIZE;
297 PRInt32 writeThisMany = UDP_AMOUNT_TO_WRITE;
298 int i;
299
300
301 DPRINTF("udpsrv: UDP_Client(): starting\n" );
302
303 /* --- Create the socket --- */
304 cltSock = PR_NewUDPSocket();
305 if ( cltSock == NULL )
306 {
307 passed = PR_FALSE;
308 if (debug_mode)
309 PR_fprintf(output,
310 "udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
311 return;
312 }
313
314 /* --- Initialize the sockaddr_in structure --- */
315 memset( &netaddr, 0, sizeof( netaddr ));
316 netaddr.inet.family = PR_AF_INET;
317 netaddr.inet.ip = PR_htonl( MY_INADDR );
318 netaddr.inet.port = PR_htons( UDP_CLIENT_PORT );
319
320 /* --- Initialize the write buffer --- */
321 for ( i = 0; i < UDP_BUF_SIZE ; i++ )
322 cltBuf[i] = i;
323
324 /* --- Bind the socket --- */
325 while ( !bound )
326 {
327 DPRINTF("udpsrv: UDP_Client(): Binding socket\n" );
328 rv = PR_Bind( cltSock, &netaddr );
329 if ( rv < 0 )
330 {
331 if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
332 {
333 if (debug_mode)
334 PR_fprintf(output,
335 "udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
336 PR_Sleep( PR_MillisecondsToInterval( 2000 ));
337 continue;
338 }
339 else
340 {
341 passed = PR_FALSE;
342 if (debug_mode)
343 PR_fprintf(output,
344 "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
345 rv, PR_GetError() );
346 PR_Close( cltSock );
347 return;
348 }
349 }
350 else
351 bound = PR_TRUE;
352 }
353 ListNetAddr( "UDP_Client after Bind", &netaddr );
354
355 /* --- Initialize the sockaddr_in structure --- */
356 memset( &netaddr, 0, sizeof( netaddr ));
357 netaddr.inet.family = PR_AF_INET;
358 netaddr.inet.ip = PR_htonl( PEER_INADDR );
359 netaddr.inet.port = PR_htons( UDP_SERVER_PORT );
360
361 /* --- send and receive packets until no more data left */
362 while( !endOfInput )
363 {
364 /*
365 ** Signal EOF in the data stream on the last packet
366 */
367 if ( writeThisMany <= UDP_DGRAM_SIZE )
368 {
369 DPRINTF("udpsrv: UDP_Client(): Send EOF packet\n" );
370 cltBuf[0] = 'E';
371 endOfInput = PR_TRUE;
372 }
373
374 /* --- SendTo the socket --- */
375 if ( writeThisMany > UDP_DGRAM_SIZE )
376 numBytes = UDP_DGRAM_SIZE;
377 else
378 numBytes = writeThisMany;
379 writeThisMany -= numBytes;
380 {
381 char mbuf[256];
382 sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %d, numbytes: %d\n",
383 writeThisMany, numBytes );
384 DPRINTF( mbuf );
385 }
386
387 DPRINTF("udpsrv: UDP_Client(): SendTo(): socket\n" );
388 rv = PR_SendTo( cltSock, cltBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
389 if ( rv == -1 )
390 {
391 passed = PR_FALSE;
392 if (debug_mode)
393 PR_fprintf(output,
394 "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
395 PR_GetError() );
396 PR_Close( cltSock );
397 return;
398 }
399 ListNetAddr( "UDP_Client after SendTo", &netaddr );
400
401 /* --- RecvFrom the socket --- */
402 memset( cltBufin, 0, UDP_BUF_SIZE );
403 DPRINTF("udpsrv: UDP_Client(): RecvFrom(): socket\n" );
404 rv = PR_RecvFrom( cltSock, cltBufin, numBytes, 0, &netaddrx, UDP_TIMEOUT );
405 if ( rv == -1 )
406 {
407 passed = PR_FALSE;
408 if (debug_mode) PR_fprintf(output,
409 "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
410 PR_GetError() );
411 PR_Close( cltSock );
412 return;
413 }
414 ListNetAddr( "UDP_Client after RecvFrom()", &netaddr );
415 cltBytesRead += rv;
416
417 /* --- verify buffer --- */
418 for ( i = 0; i < rv ; i++ )
419 {
420 if ( cltBufin[i] != i )
421 {
422 /* --- special case, end of input --- */
423 if ( endOfInput && i == 0 && cltBufin[0] == 'E' )
424 continue;
425 passed = PR_FALSE;
426 if (debug_mode) PR_fprintf(output,
427 "udpsrv: UDP_Client(): return data mismatch\n" );
428 PR_Close( cltSock );
429 return;
430 }
431 }
432 if (debug_mode) PR_fprintf(output, ".");
433 }
434
435 /* --- Close the socket --- */
436 DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
437 rv = PR_Close( cltSock );
438 if ( rv != PR_SUCCESS )
439 {
440 passed = PR_FALSE;
441 if (debug_mode) PR_fprintf(output,
442 "udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
443 return;
444 }
445 DPRINTF("udpsrv: UDP_Client(): ending\n" );
446} /* --- end UDP_Client() --- */
447
448/********************************************************************
449** main() -- udpsrv
450**
451** arguments:
452**
453** Returns:
454** 0 -- Successful execution
455** 1 -- Test failed.
456**
457** Description:
458**
459** Standard test case setup.
460**
461** Calls the function UDP_Server()
462**
463********************************************************************
464*/
465
466int main(int argc, char **argv)
467{
468 PRThread *srv, *clt;
469/* The command line argument: -d is used to determine if the test is being run
470 in debug mode. The regress tool requires only one line output:PASS or FAIL.
471 All of the printfs associated with this test has been handled with a if (debug_mode)
472 test.
473 Usage: test_name -d -v
474 */
475 PLOptStatus os;
476 PLOptState *opt = PL_CreateOptState(argc, argv, "dv");
477 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
478 {
479 if (PL_OPT_BAD == os) continue;
480 switch (opt->option)
481 {
482 case 'd': /* debug mode */
483 debug_mode = 1;
484 break;
485 case 'v': /* verbose mode */
486 _debug_on = 1;
487 break;
488 default:
489 break;
490 }
491 }
492 PL_DestroyOptState(opt);
493
494 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
495 PR_STDIO_INIT();
496 output = PR_STDERR;
497
498#ifdef XP_MAC
499 SetupMacPrintfLog("udpsrv.log");
500#endif
501
502 PR_SetConcurrency(4);
503
504 /*
505 ** Create the Server thread
506 */
507 DPRINTF( "udpsrv: Creating Server Thread\n" );
508 srv = PR_CreateThread( PR_USER_THREAD,
509 UDP_Server,
510 (void *) 0,
511 PR_PRIORITY_LOW,
512 PR_LOCAL_THREAD,
513 PR_JOINABLE_THREAD,
514 0 );
515 if ( srv == NULL )
516 {
517 if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
518 passed = PR_FALSE;
519 }
520
521 /*
522 ** Give the Server time to Start
523 */
524 DPRINTF( "udpsrv: Pausing to allow Server to start\n" );
525 PR_Sleep( PR_MillisecondsToInterval(200) );
526
527 /*
528 ** Create the Client thread
529 */
530 DPRINTF( "udpsrv: Creating Client Thread\n" );
531 clt = PR_CreateThread( PR_USER_THREAD,
532 UDP_Client,
533 (void *) 0,
534 PR_PRIORITY_LOW,
535 PR_LOCAL_THREAD,
536 PR_JOINABLE_THREAD,
537 0 );
538 if ( clt == NULL )
539 {
540 if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
541 passed = PR_FALSE;
542 }
543
544 /*
545 **
546 */
547 DPRINTF("udpsrv: Waiting to join Server & Client Threads\n" );
548 PR_JoinThread( srv );
549 PR_JoinThread( clt );
550
551 /*
552 ** Evaluate test results
553 */
554 if (debug_mode) PR_fprintf(output, "\n\nudpsrv: main(): cltBytesRead(%ld), \
555 srvBytesRead(%ld), expected(%ld)\n",
556 cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE );
557 if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE )
558 {
559 passed = PR_FALSE;
560 }
561 PR_Cleanup();
562 if ( passed )
563 return 0;
564 else
565 return 1;
566} /* --- end main() --- */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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