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
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/
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
15 * The Original Code is the Netscape Portable Runtime (NSPR).
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.
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.
36 * ***** END LICENSE BLOCK ***** */
54 ** Testing layering of I/O
57 ** A thread that acts as a server. It creates a TCP listener with a dummy
58 ** layer pushed on top. Then listens for incoming connections. Each connection
59 ** request for connection will be layered as well, accept one request, echo
63 ** Pretty much what you'd expect.
66 static PRFileDesc
*logFile
;
67 static PRDescIdentity identity
;
68 static PRNetAddr server_address
;
70 static PRIOMethods myMethods
;
72 typedef enum {rcv_get_debit
, rcv_send_credit
, rcv_data
} RcvState
;
73 typedef enum {xmt_send_debit
, xmt_recv_credit
, xmt_data
} XmtState
;
79 PRInt32 rcvreq
, rcvinprogress
;
80 PRInt32 xmtreq
, xmtinprogress
;
83 typedef enum Verbosity
{silent
, quiet
, chatty
, noisy
} Verbosity
;
85 static PRIntn minor_iterations
= 5;
86 static PRIntn major_iterations
= 1;
87 static Verbosity verbosity
= quiet
;
88 static PRUint16 default_port
= 12273;
90 static PRFileDesc
*PushLayer(PRFileDesc
*stack
)
93 PRFileDesc
*layer
= PR_CreateIOLayerStub(identity
, &myMethods
);
94 layer
->secret
= PR_NEWZAP(PRFilePrivate
);
95 rv
= PR_PushIOLayer(stack
, PR_GetLayersIdentity(stack
), layer
);
96 PR_ASSERT(PR_SUCCESS
== rv
);
97 if (verbosity
> quiet
)
98 PR_fprintf(logFile
, "Pushed layer(0x%x) onto stack(0x%x)\n", layer
, stack
);
102 static PRFileDesc
*PopLayer(PRFileDesc
*stack
)
104 PRFileDesc
*popped
= PR_PopIOLayer(stack
, identity
);
105 if (verbosity
> quiet
)
106 PR_fprintf(logFile
, "Popped layer(0x%x) from stack(0x%x)\n", popped
, stack
);
107 PR_DELETE(popped
->secret
);
108 popped
->dtor(popped
);
112 static void PR_CALLBACK
Client(void *arg
)
119 PRIntn empty_flags
= 0;
120 PRIntn bytes_read
, bytes_sent
;
121 PRFileDesc
*stack
= (PRFileDesc
*)arg
;
123 /* Initialize the buffer so that Purify won't complain */
124 memset(buffer
, 0, sizeof(buffer
));
126 rv
= PR_Connect(stack
, &server_address
, PR_INTERVAL_NO_TIMEOUT
);
127 if ((PR_FAILURE
== rv
) && (PR_IN_PROGRESS_ERROR
== PR_GetError()))
129 if (verbosity
> quiet
)
130 PR_fprintf(logFile
, "Client connect 'in progress'\n");
134 polldesc
.out_flags
= 0;
135 polldesc
.in_flags
= PR_POLL_WRITE
| PR_POLL_EXCEPT
;
136 ready
= PR_Poll(&polldesc
, 1, PR_INTERVAL_NO_TIMEOUT
);
137 if ((1 != ready
) /* if not 1, then we're dead */
138 || (0 == (polldesc
.in_flags
& polldesc
.out_flags
)))
139 { PR_ASSERT(!"Whoa!"); break; }
140 if (verbosity
> quiet
)
142 logFile
, "Client connect 'in progress' [0x%x]\n",
144 rv
= PR_GetConnectStatus(&polldesc
);
145 if ((PR_FAILURE
== rv
)
146 && (PR_IN_PROGRESS_ERROR
!= PR_GetError())) break;
147 } while (PR_FAILURE
== rv
);
149 PR_ASSERT(PR_SUCCESS
== rv
);
150 if (verbosity
> chatty
)
151 PR_fprintf(logFile
, "Client created connection\n");
153 for (mits
= 0; mits
< minor_iterations
; ++mits
)
156 if (verbosity
> quiet
)
157 PR_fprintf(logFile
, "Client sending %d bytes\n", sizeof(buffer
));
160 if (verbosity
> chatty
)
162 logFile
, "Client sending %d bytes\n",
163 sizeof(buffer
) - bytes_sent
);
165 stack
, buffer
+ bytes_sent
, sizeof(buffer
) - bytes_sent
,
166 empty_flags
, PR_INTERVAL_NO_TIMEOUT
);
167 if (verbosity
> chatty
)
168 PR_fprintf(logFile
, "Client send status [%d]\n", ready
);
169 if (0 < ready
) bytes_sent
+= ready
;
170 else if ((-1 == ready
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError()))
173 polldesc
.out_flags
= 0;
174 polldesc
.in_flags
= PR_POLL_WRITE
;
175 ready
= PR_Poll(&polldesc
, 1, PR_INTERVAL_NO_TIMEOUT
);
176 if ((1 != ready
) /* if not 1, then we're dead */
177 || (0 == (polldesc
.in_flags
& polldesc
.out_flags
)))
178 { PR_ASSERT(!"Whoa!"); break; }
181 } while (bytes_sent
< sizeof(buffer
));
182 PR_ASSERT(sizeof(buffer
) == bytes_sent
);
187 if (verbosity
> chatty
)
189 logFile
, "Client receiving %d bytes\n",
190 bytes_sent
- bytes_read
);
192 stack
, buffer
+ bytes_read
, bytes_sent
- bytes_read
,
193 empty_flags
, PR_INTERVAL_NO_TIMEOUT
);
194 if (verbosity
> chatty
)
196 logFile
, "Client receive status [%d]\n", ready
);
197 if (0 < ready
) bytes_read
+= ready
;
198 else if ((-1 == ready
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError()))
201 polldesc
.out_flags
= 0;
202 polldesc
.in_flags
= PR_POLL_READ
;
203 ready
= PR_Poll(&polldesc
, 1, PR_INTERVAL_NO_TIMEOUT
);
204 if ((1 != ready
) /* if not 1, then we're dead */
205 || (0 == (polldesc
.in_flags
& polldesc
.out_flags
)))
206 { PR_ASSERT(!"Whoa!"); break; }
209 } while (bytes_read
< bytes_sent
);
210 if (verbosity
> chatty
)
211 PR_fprintf(logFile
, "Client received %d bytes\n", bytes_read
);
212 PR_ASSERT(bytes_read
== bytes_sent
);
215 if (verbosity
> quiet
)
216 PR_fprintf(logFile
, "Client shutting down stack\n");
218 rv
= PR_Shutdown(stack
, PR_SHUTDOWN_BOTH
); PR_ASSERT(PR_SUCCESS
== rv
);
221 static void PR_CALLBACK
Server(void *arg
)
227 PRUintn empty_flags
= 0;
228 struct PRPollDesc polldesc
;
229 PRIntn bytes_read
, bytes_sent
;
230 PRFileDesc
*stack
= (PRFileDesc
*)arg
;
231 PRNetAddr client_address
;
235 if (verbosity
> chatty
)
236 PR_fprintf(logFile
, "Server accepting connection\n");
237 service
= PR_Accept(stack
, &client_address
, PR_INTERVAL_NO_TIMEOUT
);
238 if (verbosity
> chatty
)
239 PR_fprintf(logFile
, "Server accept status [0x%p]\n", service
);
240 if ((NULL
== service
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError()))
243 polldesc
.out_flags
= 0;
244 polldesc
.in_flags
= PR_POLL_READ
| PR_POLL_EXCEPT
;
245 ready
= PR_Poll(&polldesc
, 1, PR_INTERVAL_NO_TIMEOUT
);
246 if ((1 != ready
) /* if not 1, then we're dead */
247 || (0 == (polldesc
.in_flags
& polldesc
.out_flags
)))
248 { PR_ASSERT(!"Whoa!"); break; }
250 } while (NULL
== service
);
251 PR_ASSERT(NULL
!= service
);
253 if (verbosity
> quiet
)
254 PR_fprintf(logFile
, "Server accepting connection\n");
261 if (verbosity
> chatty
)
263 logFile
, "Server receiving %d bytes\n",
264 sizeof(buffer
) - bytes_read
);
266 service
, buffer
+ bytes_read
, sizeof(buffer
) - bytes_read
,
267 empty_flags
, PR_INTERVAL_NO_TIMEOUT
);
268 if (verbosity
> chatty
)
269 PR_fprintf(logFile
, "Server receive status [%d]\n", ready
);
270 if (0 < ready
) bytes_read
+= ready
;
271 else if ((-1 == ready
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError()))
273 polldesc
.fd
= service
;
274 polldesc
.out_flags
= 0;
275 polldesc
.in_flags
= PR_POLL_READ
;
276 ready
= PR_Poll(&polldesc
, 1, PR_INTERVAL_NO_TIMEOUT
);
277 if ((1 != ready
) /* if not 1, then we're dead */
278 || (0 == (polldesc
.in_flags
& polldesc
.out_flags
)))
279 { PR_ASSERT(!"Whoa!"); break; }
282 } while (bytes_read
< sizeof(buffer
));
286 if (verbosity
> chatty
)
287 PR_fprintf(logFile
, "Server received %d bytes\n", bytes_read
);
288 PR_ASSERT(bytes_read
> 0);
294 service
, buffer
+ bytes_sent
, bytes_read
- bytes_sent
,
295 empty_flags
, PR_INTERVAL_NO_TIMEOUT
);
300 else if ((-1 == ready
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError()))
302 polldesc
.fd
= service
;
303 polldesc
.out_flags
= 0;
304 polldesc
.in_flags
= PR_POLL_WRITE
;
305 ready
= PR_Poll(&polldesc
, 1, PR_INTERVAL_NO_TIMEOUT
);
306 if ((1 != ready
) /* if not 1, then we're dead */
307 || (0 == (polldesc
.in_flags
& polldesc
.out_flags
)))
308 { PR_ASSERT(!"Whoa!"); break; }
311 } while (bytes_sent
< bytes_read
);
312 PR_ASSERT(bytes_read
== bytes_sent
);
313 if (verbosity
> chatty
)
314 PR_fprintf(logFile
, "Server sent %d bytes\n", bytes_sent
);
316 } while (0 != bytes_read
);
318 if (verbosity
> quiet
)
319 PR_fprintf(logFile
, "Server shutting down stack\n");
320 rv
= PR_Shutdown(service
, PR_SHUTDOWN_BOTH
); PR_ASSERT(PR_SUCCESS
== rv
);
321 rv
= PR_Close(service
); PR_ASSERT(PR_SUCCESS
== rv
);
325 static PRStatus PR_CALLBACK
MyClose(PRFileDesc
*fd
)
327 PR_DELETE(fd
->secret
); /* manage my secret file object */
328 return (PR_GetDefaultIOMethods())->close(fd
); /* let him do all the work */
331 static PRInt16 PR_CALLBACK
MyPoll(
332 PRFileDesc
*fd
, PRInt16 in_flags
, PRInt16
*out_flags
)
334 PRInt16 my_flags
, new_flags
;
335 PRFilePrivate
*mine
= (PRFilePrivate
*)fd
->secret
;
336 if (0 != (PR_POLL_READ
& in_flags
))
338 /* client thinks he's reading */
339 switch (mine
->rcvstate
)
341 case rcv_send_credit
:
342 my_flags
= (in_flags
& ~PR_POLL_READ
) | PR_POLL_WRITE
;
350 else if (0 != (PR_POLL_WRITE
& in_flags
))
352 /* client thinks he's writing */
353 switch (mine
->xmtstate
)
355 case xmt_recv_credit
:
356 my_flags
= (in_flags
& ~PR_POLL_WRITE
) | PR_POLL_READ
;
364 else PR_ASSERT(!"How'd I get here?");
365 new_flags
= (fd
->lower
->methods
->poll
)(fd
->lower
, my_flags
, out_flags
);
366 if (verbosity
> chatty
)
368 logFile
, "Poll [i: 0x%x, m: 0x%x, o: 0x%x, n: 0x%x]\n",
369 in_flags
, my_flags
, *out_flags
, new_flags
);
373 static PRFileDesc
* PR_CALLBACK
MyAccept(
374 PRFileDesc
*fd
, PRNetAddr
*addr
, PRIntervalTime timeout
)
377 PRFileDesc
*newfd
, *layer
= fd
;
378 PRFileDesc
*newstack
;
379 PRFilePrivate
*newsecret
;
381 PR_ASSERT(fd
!= NULL
);
382 PR_ASSERT(fd
->lower
!= NULL
);
384 newstack
= PR_NEW(PRFileDesc
);
385 if (NULL
== newstack
)
387 PR_SetError(PR_OUT_OF_MEMORY_ERROR
, 0);
390 newsecret
= PR_NEW(PRFilePrivate
);
391 if (NULL
== newsecret
)
394 PR_SetError(PR_OUT_OF_MEMORY_ERROR
, 0);
397 *newstack
= *fd
; /* make a copy of the accepting layer */
398 *newsecret
= *fd
->secret
;
399 newstack
->secret
= newsecret
;
401 newfd
= (fd
->lower
->methods
->accept
)(fd
->lower
, addr
, timeout
);
404 PR_DELETE(newsecret
);
409 /* this PR_PushIOLayer call cannot fail */
410 rv
= PR_PushIOLayer(newfd
, PR_TOP_IO_LAYER
, newstack
);
411 PR_ASSERT(PR_SUCCESS
== rv
);
412 return newfd
; /* that's it */
415 static PRInt32 PR_CALLBACK
MyRecv(
416 PRFileDesc
*fd
, void *buf
, PRInt32 amount
,
417 PRIntn flags
, PRIntervalTime timeout
)
421 PRFileDesc
*lo
= fd
->lower
;
422 PRFilePrivate
*mine
= (PRFilePrivate
*)fd
->secret
;
426 switch (mine
->rcvstate
)
429 b
= (char*)&mine
->rcvreq
;
430 mine
->rcvreq
= amount
;
431 rv
= lo
->methods
->recv(
432 lo
, b
+ mine
->rcvinprogress
,
433 sizeof(mine
->rcvreq
) - mine
->rcvinprogress
, flags
, timeout
);
434 if (0 == rv
) goto closed
;
435 if ((-1 == rv
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError())) break;
436 mine
->rcvinprogress
+= rv
; /* accumulate the read */
437 if (mine
->rcvinprogress
< sizeof(mine
->rcvreq
)) break; /* loop */
438 mine
->rcvstate
= rcv_send_credit
;
439 mine
->rcvinprogress
= 0;
440 case rcv_send_credit
:
441 b
= (char*)&mine
->rcvreq
;
442 rv
= lo
->methods
->send(
443 lo
, b
+ mine
->rcvinprogress
,
444 sizeof(mine
->rcvreq
) - mine
->rcvinprogress
, flags
, timeout
);
445 if ((-1 == rv
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError())) break;
446 mine
->rcvinprogress
+= rv
; /* accumulate the read */
447 if (mine
->rcvinprogress
< sizeof(mine
->rcvreq
)) break; /* loop */
448 mine
->rcvstate
= rcv_data
;
449 mine
->rcvinprogress
= 0;
452 rv
= lo
->methods
->recv(
453 lo
, b
+ mine
->rcvinprogress
,
454 mine
->rcvreq
- mine
->rcvinprogress
, flags
, timeout
);
455 if (0 == rv
) goto closed
;
456 if ((-1 == rv
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError())) break;
457 mine
->rcvinprogress
+= rv
; /* accumulate the read */
458 if (mine
->rcvinprogress
< amount
) break; /* loop */
459 mine
->rcvstate
= rcv_get_debit
;
460 mine
->rcvinprogress
= 0;
461 return mine
->rcvreq
; /* << -- that's it! */
468 mine
->rcvinprogress
= 0;
469 mine
->rcvstate
= rcv_get_debit
;
473 static PRInt32 PR_CALLBACK
MySend(
474 PRFileDesc
*fd
, const void *buf
, PRInt32 amount
,
475 PRIntn flags
, PRIntervalTime timeout
)
479 PRFileDesc
*lo
= fd
->lower
;
480 PRFilePrivate
*mine
= (PRFilePrivate
*)fd
->secret
;
484 switch (mine
->xmtstate
)
487 b
= (char*)&mine
->xmtreq
;
488 mine
->xmtreq
= amount
;
489 rv
= lo
->methods
->send(
490 lo
, b
- mine
->xmtinprogress
,
491 sizeof(mine
->xmtreq
) - mine
->xmtinprogress
, flags
, timeout
);
492 if ((-1 == rv
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError())) break;
493 mine
->xmtinprogress
+= rv
;
494 if (mine
->xmtinprogress
< sizeof(mine
->xmtreq
)) break;
495 mine
->xmtstate
= xmt_recv_credit
;
496 mine
->xmtinprogress
= 0;
497 case xmt_recv_credit
:
498 b
= (char*)&mine
->xmtreq
;
499 rv
= lo
->methods
->recv(
500 lo
, b
+ mine
->xmtinprogress
,
501 sizeof(mine
->xmtreq
) - mine
->xmtinprogress
, flags
, timeout
);
502 if ((-1 == rv
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError())) break;
503 mine
->xmtinprogress
+= rv
;
504 if (mine
->xmtinprogress
< sizeof(mine
->xmtreq
)) break;
505 mine
->xmtstate
= xmt_data
;
506 mine
->xmtinprogress
= 0;
509 rv
= lo
->methods
->send(
510 lo
, b
+ mine
->xmtinprogress
,
511 mine
->xmtreq
- mine
->xmtinprogress
, flags
, timeout
);
512 if ((-1 == rv
) && (PR_WOULD_BLOCK_ERROR
== PR_GetError())) break;
513 mine
->xmtinprogress
+= rv
;
514 if (mine
->xmtinprogress
< amount
) break;
515 mine
->xmtstate
= xmt_send_debit
;
516 mine
->xmtinprogress
= 0;
517 return mine
->xmtreq
; /* <<-- That's the one! */
525 static Verbosity
ChangeVerbosity(Verbosity verbosity
, PRIntn delta
)
527 PRIntn verbage
= (PRIntn
)verbosity
+ delta
;
528 if (verbage
< (PRIntn
)silent
) verbage
= (PRIntn
)silent
;
529 else if (verbage
> (PRIntn
)noisy
) verbage
= (PRIntn
)noisy
;
530 return (Verbosity
)verbage
;
531 } /* ChangeVerbosity */
533 PRIntn
main(PRIntn argc
, char **argv
)
537 PRFileDesc
*client
, *service
;
538 PRNetAddr any_address
;
539 const char *server_name
= NULL
;
540 const PRIOMethods
*stubMethods
;
541 PRThread
*client_thread
, *server_thread
;
542 PRThreadScope thread_scope
= PR_LOCAL_THREAD
;
543 PRSocketOptionData socket_noblock
, socket_nodelay
;
544 PLOptState
*opt
= PL_CreateOptState(argc
, argv
, "dqGC:c:p:");
545 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
547 if (PL_OPT_BAD
== os
) continue;
551 server_name
= opt
->value
;
553 case 'd': /* debug mode */
554 if (verbosity
< noisy
)
555 verbosity
= ChangeVerbosity(verbosity
, 1);
557 case 'q': /* debug mode */
558 if (verbosity
> silent
)
559 verbosity
= ChangeVerbosity(verbosity
, -1);
561 case 'G': /* use global threads */
562 thread_scope
= PR_GLOBAL_THREAD
;
564 case 'C': /* number of threads waiting */
565 major_iterations
= atoi(opt
->value
);
567 case 'c': /* number of client threads */
568 minor_iterations
= atoi(opt
->value
);
570 case 'p': /* default port */
571 default_port
= atoi(opt
->value
);
577 PL_DestroyOptState(opt
);
580 logFile
= PR_GetSpecialFD(PR_StandardError
);
581 identity
= PR_GetUniqueIdentity("Dummy");
582 stubMethods
= PR_GetDefaultIOMethods();
585 ** The protocol we're going to implement is one where in order to initiate
586 ** a send, the sender must first solicit permission. Therefore, every
587 ** send is really a send - receive - send sequence.
589 myMethods
= *stubMethods
; /* first get the entire batch */
590 myMethods
.accept
= MyAccept
; /* then override the ones we care about */
591 myMethods
.recv
= MyRecv
; /* then override the ones we care about */
592 myMethods
.send
= MySend
; /* then override the ones we care about */
593 myMethods
.close
= MyClose
; /* then override the ones we care about */
594 myMethods
.poll
= MyPoll
; /* then override the ones we care about */
596 if (NULL
== server_name
)
597 rv
= PR_InitializeNetAddr(
598 PR_IpAddrLoopback
, default_port
, &server_address
);
601 rv
= PR_StringToNetAddr(server_name
, &server_address
);
602 PR_ASSERT(PR_SUCCESS
== rv
);
603 rv
= PR_InitializeNetAddr(
604 PR_IpAddrNull
, default_port
, &server_address
);
606 PR_ASSERT(PR_SUCCESS
== rv
);
608 socket_noblock
.value
.non_blocking
= PR_TRUE
;
609 socket_noblock
.option
= PR_SockOpt_Nonblocking
;
610 socket_nodelay
.value
.no_delay
= PR_TRUE
;
611 socket_nodelay
.option
= PR_SockOpt_NoDelay
;
613 /* one type w/o layering */
615 while (major_iterations
-- > 0)
617 if (verbosity
> silent
)
618 PR_fprintf(logFile
, "Beginning non-layered test\n");
620 client
= PR_NewTCPSocket(); PR_ASSERT(NULL
!= client
);
621 service
= PR_NewTCPSocket(); PR_ASSERT(NULL
!= service
);
623 rv
= PR_SetSocketOption(client
, &socket_noblock
);
624 PR_ASSERT(PR_SUCCESS
== rv
);
625 rv
= PR_SetSocketOption(service
, &socket_noblock
);
626 PR_ASSERT(PR_SUCCESS
== rv
);
627 rv
= PR_SetSocketOption(client
, &socket_nodelay
);
628 PR_ASSERT(PR_SUCCESS
== rv
);
629 rv
= PR_SetSocketOption(service
, &socket_nodelay
);
630 PR_ASSERT(PR_SUCCESS
== rv
);
632 rv
= PR_InitializeNetAddr(PR_IpAddrAny
, default_port
, &any_address
);
633 PR_ASSERT(PR_SUCCESS
== rv
);
634 rv
= PR_Bind(service
, &any_address
); PR_ASSERT(PR_SUCCESS
== rv
);
635 rv
= PR_Listen(service
, 10); PR_ASSERT(PR_SUCCESS
== rv
);
637 server_thread
= PR_CreateThread(
638 PR_USER_THREAD
, Server
, service
,
639 PR_PRIORITY_HIGH
, thread_scope
,
640 PR_JOINABLE_THREAD
, 16 * 1024);
641 PR_ASSERT(NULL
!= server_thread
);
643 client_thread
= PR_CreateThread(
644 PR_USER_THREAD
, Client
, client
,
645 PR_PRIORITY_NORMAL
, thread_scope
,
646 PR_JOINABLE_THREAD
, 16 * 1024);
647 PR_ASSERT(NULL
!= client_thread
);
649 rv
= PR_JoinThread(client_thread
);
650 PR_ASSERT(PR_SUCCESS
== rv
);
651 rv
= PR_JoinThread(server_thread
);
652 PR_ASSERT(PR_SUCCESS
== rv
);
654 rv
= PR_Close(client
); PR_ASSERT(PR_SUCCESS
== rv
);
655 rv
= PR_Close(service
); PR_ASSERT(PR_SUCCESS
== rv
);
656 if (verbosity
> silent
)
657 PR_fprintf(logFile
, "Ending non-layered test\n");
660 if (verbosity
> silent
)
661 PR_fprintf(logFile
, "Beginning layered test\n");
662 client
= PR_NewTCPSocket(); PR_ASSERT(NULL
!= client
);
663 service
= PR_NewTCPSocket(); PR_ASSERT(NULL
!= service
);
665 rv
= PR_SetSocketOption(client
, &socket_noblock
);
666 PR_ASSERT(PR_SUCCESS
== rv
);
667 rv
= PR_SetSocketOption(service
, &socket_noblock
);
668 PR_ASSERT(PR_SUCCESS
== rv
);
669 rv
= PR_SetSocketOption(client
, &socket_nodelay
);
670 PR_ASSERT(PR_SUCCESS
== rv
);
671 rv
= PR_SetSocketOption(service
, &socket_nodelay
);
672 PR_ASSERT(PR_SUCCESS
== rv
);
677 rv
= PR_InitializeNetAddr(PR_IpAddrAny
, default_port
, &any_address
);
678 PR_ASSERT(PR_SUCCESS
== rv
);
679 rv
= PR_Bind(service
, &any_address
); PR_ASSERT(PR_SUCCESS
== rv
);
680 rv
= PR_Listen(service
, 10); PR_ASSERT(PR_SUCCESS
== rv
);
682 server_thread
= PR_CreateThread(
683 PR_USER_THREAD
, Server
, service
,
684 PR_PRIORITY_HIGH
, thread_scope
,
685 PR_JOINABLE_THREAD
, 16 * 1024);
686 PR_ASSERT(NULL
!= server_thread
);
688 client_thread
= PR_CreateThread(
689 PR_USER_THREAD
, Client
, client
,
690 PR_PRIORITY_NORMAL
, thread_scope
,
691 PR_JOINABLE_THREAD
, 16 * 1024);
692 PR_ASSERT(NULL
!= client_thread
);
694 rv
= PR_JoinThread(client_thread
);
695 PR_ASSERT(PR_SUCCESS
== rv
);
696 rv
= PR_JoinThread(server_thread
);
697 PR_ASSERT(PR_SUCCESS
== rv
);
699 rv
= PR_Close(PopLayer(client
)); PR_ASSERT(PR_SUCCESS
== rv
);
700 rv
= PR_Close(PopLayer(service
)); PR_ASSERT(PR_SUCCESS
== rv
);
701 if (verbosity
> silent
)
702 PR_fprintf(logFile
, "Ending layered test\n");