VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/nbconn.c@ 55761

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

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.9 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 * A test for nonblocking connect. Functions tested include PR_Connect,
40 * PR_Poll, and PR_GetConnectStatus.
41 *
42 * The test should be invoked with a host name, for example:
43 * nbconn www.netscape.com
44 * It will do a nonblocking connect to port 80 (HTTP) on that host,
45 * and when connected, issue the "GET /" HTTP command.
46 *
47 * You should run this test in three ways:
48 * 1. To a known web site, such as www.netscape.com. The HTML of the
49 * top-level page at the web site should be printed.
50 * 2. To a machine not running a web server at port 80. This test should
51 * fail. Ideally the error code should be PR_CONNECT_REFUSED_ERROR.
52 * But it is possible to return PR_UNKNOWN_ERROR on certain platforms.
53 * 3. To an unreachable machine, for example, a machine that is off line.
54 * The test should fail after the connect times out. Ideally the
55 * error code should be PR_IO_TIMEOUT_ERROR, but it is possible to
56 * return PR_UNKNOWN_ERROR on certain platforms.
57 */
58
59#include "nspr.h"
60#include "plgetopt.h"
61#include <stdio.h>
62
63#ifdef XP_MAC
64#define printf PR_LogPrint
65extern void SetupMacPrintfLog(char *logFile);
66static char *hosts[4] = {"cynic", "warp", "gandalf", "neon"};
67#endif
68
69#define SERVER_MAX_BIND_COUNT 100
70#define DATA_BUF_SIZE 256
71#define TCP_SERVER_PORT 10000
72#define TCP_UNUSED_PORT 211
73
74typedef struct Server_Param {
75 PRFileDesc *sp_fd; /* server port */
76} Server_Param;
77static void PR_CALLBACK TCP_Server(void *arg);
78
79int _debug_on;
80#define DPRINTF(arg) if (_debug_on) printf arg
81
82static PRIntn connection_success_test();
83static PRIntn connection_failure_test();
84
85int main(int argc, char **argv)
86{
87 PRHostEnt he;
88 char buf[1024];
89 PRNetAddr addr;
90 PRPollDesc pd;
91 PRStatus rv;
92 PRSocketOptionData optData;
93 const char *hostname = NULL;
94 PRIntn default_case, n, bytes_read, bytes_sent;
95 PRInt32 failed_already = 0;
96#ifdef XP_MAC
97 int index;
98 PRIntervalTime timeout;
99#endif
100
101 /*
102 * -d debug mode
103 */
104
105 PLOptStatus os;
106 PLOptState *opt = PL_CreateOptState(argc, argv, "d");
107 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
108 {
109 if (PL_OPT_BAD == os) continue;
110 switch (opt->option)
111 {
112 case 0: /* debug mode */
113 hostname = opt->value;
114 break;
115 case 'd': /* debug mode */
116 _debug_on = 1;
117 break;
118 default:
119 break;
120 }
121 }
122 PL_DestroyOptState(opt);
123
124#ifdef XP_MAC
125 SetupMacPrintfLog("nbconn.log");
126 for (index=0; index<4; index++) {
127 argv[1] = hosts[index];
128 timeout = PR_INTERVAL_NO_TIMEOUT;
129 if (index == 3)
130 timeout = PR_SecondsToInterval(10UL);
131#endif
132
133
134 PR_STDIO_INIT();
135#ifndef XP_MAC
136 if (hostname)
137 default_case = 0;
138 else
139 default_case = 1;
140#endif
141
142 if (default_case) {
143
144 /*
145 * In the default case the following tests are executed:
146 * 1. successful connection: a server thread accepts a connection
147 * from the main thread
148 * 2. unsuccessful connection: the main thread tries to connect to a
149 * non-existent port and expects to get an error
150 */
151 rv = connection_success_test();
152 if (rv == 0)
153 rv = connection_failure_test();
154 return rv;
155 } else {
156 PRFileDesc *sock;
157
158 if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) {
159 printf( "Unknown host: %s\n", argv[1]);
160 exit(1);
161 } else {
162 printf( "host: %s\n", buf);
163 }
164 PR_EnumerateHostEnt(0, &he, 80, &addr);
165
166 sock = PR_NewTCPSocket();
167 optData.option = PR_SockOpt_Nonblocking;
168 optData.value.non_blocking = PR_TRUE;
169 PR_SetSocketOption(sock, &optData);
170 rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
171 if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
172 printf( "Connect in progress\n");
173 }
174
175 pd.fd = sock;
176 pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
177#ifndef XP_MAC
178 n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
179#else
180 n = PR_Poll(&pd, 1, timeout);
181#endif
182 if (n == -1) {
183 printf( "PR_Poll failed\n");
184 exit(1);
185 }
186 printf( "PR_Poll returns %d\n", n);
187 if (pd.out_flags & PR_POLL_READ) {
188 printf( "PR_POLL_READ\n");
189 }
190 if (pd.out_flags & PR_POLL_WRITE) {
191 printf( "PR_POLL_WRITE\n");
192 }
193 if (pd.out_flags & PR_POLL_EXCEPT) {
194 printf( "PR_POLL_EXCEPT\n");
195 }
196 if (pd.out_flags & PR_POLL_ERR) {
197 printf( "PR_POLL_ERR\n");
198 }
199 if (pd.out_flags & PR_POLL_NVAL) {
200 printf( "PR_POLL_NVAL\n");
201 }
202
203 if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
204 printf("PR_GetConnectStatus: connect succeeded\n");
205 /* Mac and Win16 have trouble printing to the console. */
206#if !defined(XP_MAC) && !defined(WIN16)
207 PR_Write(sock, "GET /\r\n\r\n", 9);
208 PR_Shutdown(sock, PR_SHUTDOWN_SEND);
209 pd.in_flags = PR_POLL_READ;
210 while (1) {
211 n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
212 printf( "poll returns %d\n", n);
213 n = PR_Read(sock, buf, sizeof(buf));
214 printf( "read returns %d\n", n);
215 if (n <= 0) {
216 break;
217 }
218 PR_Write(PR_STDOUT, buf, n);
219 }
220#endif
221 } else {
222 if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
223 printf( "PR_GetConnectStatus: connect still in progress\n");
224 exit(1);
225 }
226 printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
227 PR_GetError(), PR_GetOSError());
228 }
229 PR_Close(sock);
230#ifdef XP_MAC
231 } /* end of for loop */
232#endif
233 printf( "PASS\n");
234 return 0;
235
236 }
237}
238
239
240/*
241 * TCP Server
242 * Server Thread
243 * Accept a connection from the client and write some data
244 */
245static void PR_CALLBACK
246TCP_Server(void *arg)
247{
248 Server_Param *sp = (Server_Param *) arg;
249 PRFileDesc *sockfd, *newsockfd;
250 char data_buf[DATA_BUF_SIZE];
251 PRIntn rv, bytes_read;
252
253 sockfd = sp->sp_fd;
254 if ((newsockfd = PR_Accept(sockfd, NULL,
255 PR_INTERVAL_NO_TIMEOUT)) == NULL) {
256 fprintf(stderr,"ERROR - PR_Accept failed: (%d,%d)\n",
257 PR_GetError(), PR_GetOSError());
258 return;
259 }
260 bytes_read = 0;
261 while (bytes_read != DATA_BUF_SIZE) {
262 rv = PR_Read(newsockfd, data_buf + bytes_read ,
263 DATA_BUF_SIZE - bytes_read);
264 if (rv < 0) {
265 fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
266 PR_GetError(), PR_GetOSError());
267 PR_Close(newsockfd);
268 return;
269 }
270 PR_ASSERT(rv != 0);
271 bytes_read += rv;
272 }
273 DPRINTF(("Bytes read from client - %d\n",bytes_read));
274 rv = PR_Write(newsockfd, data_buf,DATA_BUF_SIZE);
275 if (rv < 0) {
276 fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
277 PR_GetError(), PR_GetOSError());
278 PR_Close(newsockfd);
279 return;
280 }
281 PR_ASSERT(rv == DATA_BUF_SIZE);
282 DPRINTF(("Bytes written to client - %d\n",rv));
283 PR_Close(newsockfd);
284}
285
286
287/*
288 * test for successful connection using a non-blocking socket
289 */
290static PRIntn
291connection_success_test()
292{
293 PRFileDesc *sockfd = NULL, *conn_fd = NULL;
294 PRNetAddr netaddr;
295 PRInt32 i, rv;
296 PRPollDesc pd;
297 PRSocketOptionData optData;
298 PRThread *thr = NULL;
299 Server_Param sp;
300 char send_buf[DATA_BUF_SIZE], recv_buf[DATA_BUF_SIZE];
301 PRIntn default_case, n, bytes_read, bytes_sent;
302 PRIntn failed_already = 0;
303
304 /*
305 * Create a tcp socket
306 */
307 if ((sockfd = PR_NewTCPSocket()) == NULL) {
308 fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
309 failed_already=1;
310 goto def_exit;
311 }
312 memset(&netaddr, 0 , sizeof(netaddr));
313 netaddr.inet.family = PR_AF_INET;
314 netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
315 netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
316 /*
317 * try a few times to bind server's address, if addresses are in
318 * use
319 */
320 i = 0;
321 while (PR_Bind(sockfd, &netaddr) < 0) {
322 if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
323 netaddr.inet.port += 2;
324 if (i++ < SERVER_MAX_BIND_COUNT)
325 continue;
326 }
327 fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
328 PR_GetError(), PR_GetOSError());
329 failed_already=1;
330 goto def_exit;
331 }
332
333 if (PR_Listen(sockfd, 32) < 0) {
334 fprintf(stderr,"ERROR - PR_Listen failed: (%d,%d)\n",
335 PR_GetError(), PR_GetOSError());
336 failed_already=1;
337 goto def_exit;
338 }
339
340 if (PR_GetSockName(sockfd, &netaddr) < 0) {
341 fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
342 PR_GetError(), PR_GetOSError());
343 failed_already=1;
344 goto def_exit;
345 }
346 if ((conn_fd = PR_NewTCPSocket()) == NULL) {
347 fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
348 failed_already=1;
349 goto def_exit;
350 }
351 optData.option = PR_SockOpt_Nonblocking;
352 optData.value.non_blocking = PR_TRUE;
353 PR_SetSocketOption(conn_fd, &optData);
354 rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
355 if (rv == PR_FAILURE) {
356 if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
357 DPRINTF(("Connect in progress\n"));
358 } else {
359 fprintf(stderr,"Error - PR_Connect failed: (%d, %d)\n",
360 PR_GetError(), PR_GetOSError());
361 failed_already=1;
362 goto def_exit;
363 }
364 }
365 /*
366 * Now create a thread to accept a connection
367 */
368 sp.sp_fd = sockfd;
369 thr = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void *)&sp,
370 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
371 if (thr == NULL) {
372 fprintf(stderr,"Error - PR_CreateThread failed: (%d,%d)\n",
373 PR_GetError(), PR_GetOSError());
374 failed_already=1;
375 goto def_exit;
376 }
377 DPRINTF(("Created TCP_Server thread [0x%x]\n",thr));
378 pd.fd = conn_fd;
379 pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
380#ifndef XP_MAC
381 n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
382#else
383 n = PR_Poll(&pd, 1, timeout);
384#endif
385 if (n == -1) {
386 fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
387 PR_GetError(), PR_GetOSError());
388 failed_already=1;
389 goto def_exit;
390 }
391 if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
392 PRInt32 rv;
393
394 DPRINTF(("Connection successful\n"));
395
396 /*
397 * Write some data, read it back and check data integrity to
398 * make sure the connection is good
399 */
400 pd.in_flags = PR_POLL_WRITE;
401 bytes_sent = 0;
402 memset(send_buf, 'a', DATA_BUF_SIZE);
403 while (bytes_sent != DATA_BUF_SIZE) {
404 rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
405 if (rv < 0) {
406 fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
407 PR_GetError(), PR_GetOSError());
408 failed_already=1;
409 goto def_exit;
410 }
411 PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_WRITE));
412 rv = PR_Write(conn_fd, send_buf + bytes_sent,
413 DATA_BUF_SIZE - bytes_sent);
414 if (rv < 0) {
415 fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
416 PR_GetError(), PR_GetOSError());
417 failed_already=1;
418 goto def_exit;
419 }
420 PR_ASSERT(rv > 0);
421 bytes_sent += rv;
422 }
423 DPRINTF(("Bytes written to server - %d\n",bytes_sent));
424 PR_Shutdown(conn_fd, PR_SHUTDOWN_SEND);
425 pd.in_flags = PR_POLL_READ;
426 bytes_read = 0;
427 memset(recv_buf, 0, DATA_BUF_SIZE);
428 while (bytes_read != DATA_BUF_SIZE) {
429 rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
430 if (rv < 0) {
431 fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
432 PR_GetError(), PR_GetOSError());
433 failed_already=1;
434 goto def_exit;
435 }
436 PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_READ));
437 rv = PR_Read(conn_fd, recv_buf + bytes_read ,
438 DATA_BUF_SIZE - bytes_read);
439 if (rv < 0) {
440 fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
441 PR_GetError(), PR_GetOSError());
442 failed_already=1;
443 goto def_exit;
444 }
445 PR_ASSERT(rv != 0);
446 bytes_read += rv;
447 }
448 DPRINTF(("Bytes read from server - %d\n",bytes_read));
449 /*
450 * verify the data read
451 */
452 if (memcmp(send_buf, recv_buf, DATA_BUF_SIZE) != 0) {
453 fprintf(stderr,"ERROR - data corruption\n");
454 failed_already=1;
455 goto def_exit;
456 }
457 DPRINTF(("Data integrity verified\n"));
458 } else {
459 fprintf(stderr,"PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
460 PR_GetError(), PR_GetOSError());
461 failed_already = 1;
462 goto def_exit;
463 }
464def_exit:
465 if (thr) {
466 PR_JoinThread(thr);
467 thr = NULL;
468 }
469 if (sockfd) {
470 PR_Close(sockfd);
471 sockfd = NULL;
472 }
473 if (conn_fd) {
474 PR_Close(conn_fd);
475 conn_fd = NULL;
476 }
477 if (failed_already)
478 return 1;
479 else
480 return 0;
481
482}
483
484/*
485 * test for connection to a non-existent port using a non-blocking socket
486 */
487static PRIntn
488connection_failure_test()
489{
490 PRFileDesc *sockfd = NULL, *conn_fd = NULL;
491 PRNetAddr netaddr;
492 PRInt32 i, rv;
493 PRPollDesc pd;
494 PRSocketOptionData optData;
495 PRIntn n, failed_already = 0;
496
497 /*
498 * Create a tcp socket
499 */
500 if ((sockfd = PR_NewTCPSocket()) == NULL) {
501 fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
502 failed_already=1;
503 goto def_exit;
504 }
505 memset(&netaddr, 0 , sizeof(netaddr));
506 netaddr.inet.family = PR_AF_INET;
507 netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
508 netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
509 /*
510 * try a few times to bind server's address, if addresses are in
511 * use
512 */
513 i = 0;
514 while (PR_Bind(sockfd, &netaddr) < 0) {
515 if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
516 netaddr.inet.port += 2;
517 if (i++ < SERVER_MAX_BIND_COUNT)
518 continue;
519 }
520 fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
521 PR_GetError(), PR_GetOSError());
522 failed_already=1;
523 goto def_exit;
524 }
525
526 if (PR_GetSockName(sockfd, &netaddr) < 0) {
527 fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
528 PR_GetError(), PR_GetOSError());
529 failed_already=1;
530 goto def_exit;
531 }
532#ifdef AIX
533 /*
534 * On AIX, set to unused/reserved port
535 */
536 netaddr.inet.port = PR_htons(TCP_UNUSED_PORT);
537#endif
538 if ((conn_fd = PR_NewTCPSocket()) == NULL) {
539 fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
540 failed_already=1;
541 goto def_exit;
542 }
543 optData.option = PR_SockOpt_Nonblocking;
544 optData.value.non_blocking = PR_TRUE;
545 PR_SetSocketOption(conn_fd, &optData);
546 rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
547 if (rv == PR_FAILURE) {
548 DPRINTF(("PR_Connect to a non-listen port failed: (%d, %d)\n",
549 PR_GetError(), PR_GetOSError()));
550 } else {
551 PR_ASSERT(rv == PR_SUCCESS);
552 fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n");
553 failed_already=1;
554 goto def_exit;
555 }
556 pd.fd = conn_fd;
557 pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
558#ifndef XP_MAC
559 n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
560#else
561 n = PR_Poll(&pd, 1, timeout);
562#endif
563 if (n == -1) {
564 fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
565 PR_GetError(), PR_GetOSError());
566 failed_already=1;
567 goto def_exit;
568 }
569 if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
570 PRInt32 rv;
571 fprintf(stderr,"PR_GetConnectStatus succeeded, expected to fail\n");
572 failed_already = 1;
573 goto def_exit;
574 }
575 rv = PR_GetError();
576 DPRINTF(("Connection failed, successfully with PR_Error %d\n",rv));
577def_exit:
578 if (sockfd) {
579 PR_Close(sockfd);
580 sockfd = NULL;
581 }
582 if (conn_fd) {
583 PR_Close(conn_fd);
584 conn_fd = NULL;
585 }
586 if (failed_already)
587 return 1;
588 else
589 return 0;
590
591}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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