VirtualBox

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

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

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 16.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#include "prio.h"
39#include "prprf.h"
40#include "prlog.h"
41#include "prnetdb.h"
42#include "prthread.h"
43
44#include "plerror.h"
45#include "plgetopt.h"
46#include "prwin16.h"
47
48#include <stdlib.h>
49
50/*
51** Testing layering of I/O
52**
53** The layered server
54** A thread that acts as a server. It creates a TCP listener with a dummy
55** layer pushed on top. Then listens for incoming connections. Each connection
56** request for connection will be layered as well, accept one request, echo
57** it back and close.
58**
59** The layered client
60** Pretty much what you'd expect.
61*/
62
63static PRFileDesc *logFile;
64static PRDescIdentity identity;
65static PRNetAddr server_address;
66
67static PRIOMethods myMethods;
68
69typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
70
71static PRIntn minor_iterations = 5;
72static PRIntn major_iterations = 1;
73static Verbosity verbosity = quiet;
74static PRUint16 default_port = 12273;
75
76static PRFileDesc *PushLayer(PRFileDesc *stack)
77{
78 PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods);
79 PRStatus rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
80 if (verbosity > quiet)
81 PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack);
82 PR_ASSERT(PR_SUCCESS == rv);
83 return stack;
84} /* PushLayer */
85
86static PRFileDesc *PushNewLayers(PRFileDesc *stack)
87{
88 PRDescIdentity tmp_identity;
89 PRFileDesc *layer;
90 PRStatus rv;
91
92 /* push a dummy layer */
93 tmp_identity = PR_GetUniqueIdentity("Dummy 1");
94 layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods());
95 rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
96 if (verbosity > quiet)
97 PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
98 stack);
99 PR_ASSERT(PR_SUCCESS == rv);
100
101 /* push a data procesing layer */
102 layer = PR_CreateIOLayerStub(identity, &myMethods);
103 rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
104 if (verbosity > quiet)
105 PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
106 stack);
107 PR_ASSERT(PR_SUCCESS == rv);
108
109 /* push another dummy layer */
110 tmp_identity = PR_GetUniqueIdentity("Dummy 2");
111 layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods());
112 rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
113 if (verbosity > quiet)
114 PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
115 stack);
116 PR_ASSERT(PR_SUCCESS == rv);
117 return stack;
118} /* PushLayer */
119
120#if 0
121static PRFileDesc *PopLayer(PRFileDesc *stack)
122{
123 PRFileDesc *popped = PR_PopIOLayer(stack, identity);
124 if (verbosity > quiet)
125 PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack);
126 popped->dtor(popped);
127
128 return stack;
129} /* PopLayer */
130#endif
131
132static void PR_CALLBACK Client(void *arg)
133{
134 PRStatus rv;
135 PRUint8 buffer[100];
136 PRIntn empty_flags = 0;
137 PRIntn bytes_read, bytes_sent;
138 PRFileDesc *stack = (PRFileDesc*)arg;
139
140 /* Initialize the buffer so that Purify won't complain */
141 memset(buffer, 0, sizeof(buffer));
142
143 rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
144 PR_ASSERT(PR_SUCCESS == rv);
145 while (minor_iterations-- > 0)
146 {
147 bytes_sent = PR_Send(
148 stack, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
149 PR_ASSERT(sizeof(buffer) == bytes_sent);
150 if (verbosity > chatty)
151 PR_fprintf(logFile, "Client sending %d bytes\n", bytes_sent);
152 bytes_read = PR_Recv(
153 stack, buffer, bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT);
154 if (verbosity > chatty)
155 PR_fprintf(logFile, "Client receiving %d bytes\n", bytes_read);
156 PR_ASSERT(bytes_read == bytes_sent);
157 }
158
159 if (verbosity > quiet)
160 PR_fprintf(logFile, "Client shutting down stack\n");
161
162 rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
163} /* Client */
164
165static void PR_CALLBACK Server(void *arg)
166{
167 PRStatus rv;
168 PRUint8 buffer[100];
169 PRFileDesc *service;
170 PRUintn empty_flags = 0;
171 PRIntn bytes_read, bytes_sent;
172 PRFileDesc *stack = (PRFileDesc*)arg;
173 PRNetAddr client_address;
174
175 service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
176 if (verbosity > quiet)
177 PR_fprintf(logFile, "Server accepting connection\n");
178
179 do
180 {
181 bytes_read = PR_Recv(
182 service, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
183 if (0 != bytes_read)
184 {
185 if (verbosity > chatty)
186 PR_fprintf(logFile, "Server receiving %d bytes\n", bytes_read);
187 PR_ASSERT(bytes_read > 0);
188 bytes_sent = PR_Send(
189 service, buffer, bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT);
190 if (verbosity > chatty)
191 PR_fprintf(logFile, "Server sending %d bytes\n", bytes_sent);
192 PR_ASSERT(bytes_read == bytes_sent);
193 }
194
195 } while (0 != bytes_read);
196
197 if (verbosity > quiet)
198 PR_fprintf(logFile, "Server shutting down and closing stack\n");
199 rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
200 rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
201
202} /* Server */
203
204static PRInt32 PR_CALLBACK MyRecv(
205 PRFileDesc *fd, void *buf, PRInt32 amount,
206 PRIntn flags, PRIntervalTime timeout)
207{
208 char *b = (char*)buf;
209 PRFileDesc *lo = fd->lower;
210 PRInt32 rv, readin = 0, request = 0;
211 rv = lo->methods->recv(lo, &request, sizeof(request), flags, timeout);
212 if (verbosity > chatty) PR_fprintf(
213 logFile, "MyRecv sending permission for %d bytes\n", request);
214 if (0 < rv)
215 {
216 if (verbosity > chatty) PR_fprintf(
217 logFile, "MyRecv received permission request for %d bytes\n", request);
218 rv = lo->methods->send(
219 lo, &request, sizeof(request), flags, timeout);
220 if (0 < rv)
221 {
222 if (verbosity > chatty) PR_fprintf(
223 logFile, "MyRecv sending permission for %d bytes\n", request);
224 while (readin < request)
225 {
226 rv = lo->methods->recv(
227 lo, b + readin, amount - readin, flags, timeout);
228 if (rv <= 0) break;
229 if (verbosity > chatty) PR_fprintf(
230 logFile, "MyRecv received %d bytes\n", rv);
231 readin += rv;
232 }
233 rv = readin;
234 }
235 }
236 return rv;
237} /* MyRecv */
238
239static PRInt32 PR_CALLBACK MySend(
240 PRFileDesc *fd, const void *buf, PRInt32 amount,
241 PRIntn flags, PRIntervalTime timeout)
242{
243 PRFileDesc *lo = fd->lower;
244 const char *b = (const char*)buf;
245 PRInt32 rv, wroteout = 0, request;
246 if (verbosity > chatty) PR_fprintf(
247 logFile, "MySend asking permission to send %d bytes\n", amount);
248 rv = lo->methods->send(lo, &amount, sizeof(amount), flags, timeout);
249 if (0 < rv)
250 {
251 rv = lo->methods->recv(
252 lo, &request, sizeof(request), flags, timeout);
253 if (0 < rv)
254 {
255 PR_ASSERT(request == amount);
256 if (verbosity > chatty) PR_fprintf(
257 logFile, "MySend got permission to send %d bytes\n", request);
258 while (wroteout < request)
259 {
260 rv = lo->methods->send(
261 lo, b + wroteout, request - wroteout, flags, timeout);
262 if (rv <= 0) break;
263 if (verbosity > chatty) PR_fprintf(
264 logFile, "MySend wrote %d bytes\n", rv);
265 wroteout += rv;
266 }
267 rv = amount;
268 }
269 }
270 return rv;
271} /* MySend */
272
273static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
274{
275 PRIntn verbage = (PRIntn)verbosity + delta;
276 if (verbage < (PRIntn)silent) verbage = (PRIntn)silent;
277 else if (verbage > (PRIntn)noisy) verbage = (PRIntn)noisy;
278 return (Verbosity)verbage;
279} /* ChangeVerbosity */
280
281PRIntn main(PRIntn argc, char **argv)
282{
283 PRStatus rv;
284 PRIntn mits;
285 PLOptStatus os;
286 PRFileDesc *client, *service;
287 PRFileDesc *client_stack, *service_stack;
288 PRNetAddr any_address;
289 const char *server_name = NULL;
290 const PRIOMethods *stubMethods;
291 PRThread *client_thread, *server_thread;
292 PRThreadScope thread_scope = PR_LOCAL_THREAD;
293 PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:");
294 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
295 {
296 if (PL_OPT_BAD == os) continue;
297 switch (opt->option)
298 {
299 case 0:
300 server_name = opt->value;
301 break;
302 case 'd': /* debug mode */
303 if (verbosity < noisy)
304 verbosity = ChangeVerbosity(verbosity, 1);
305 break;
306 case 'q': /* debug mode */
307 if (verbosity > silent)
308 verbosity = ChangeVerbosity(verbosity, -1);
309 break;
310 case 'G': /* use global threads */
311 thread_scope = PR_GLOBAL_THREAD;
312 break;
313 case 'C': /* number of threads waiting */
314 major_iterations = atoi(opt->value);
315 break;
316 case 'c': /* number of client threads */
317 minor_iterations = atoi(opt->value);
318 break;
319 case 'p': /* default port */
320 default_port = atoi(opt->value);
321 break;
322 default:
323 break;
324 }
325 }
326 PL_DestroyOptState(opt);
327 PR_STDIO_INIT();
328
329 logFile = PR_GetSpecialFD(PR_StandardError);
330
331 identity = PR_GetUniqueIdentity("Dummy");
332 stubMethods = PR_GetDefaultIOMethods();
333
334 /*
335 ** The protocol we're going to implement is one where in order to initiate
336 ** a send, the sender must first solicit permission. Therefore, every
337 ** send is really a send - receive - send sequence.
338 */
339 myMethods = *stubMethods; /* first get the entire batch */
340 myMethods.recv = MyRecv; /* then override the ones we care about */
341 myMethods.send = MySend; /* then override the ones we care about */
342
343 if (NULL == server_name)
344 rv = PR_InitializeNetAddr(
345 PR_IpAddrLoopback, default_port, &server_address);
346 else
347 {
348 rv = PR_StringToNetAddr(server_name, &server_address);
349 PR_ASSERT(PR_SUCCESS == rv);
350 rv = PR_InitializeNetAddr(
351 PR_IpAddrNull, default_port, &server_address);
352 }
353 PR_ASSERT(PR_SUCCESS == rv);
354
355 /* one type w/o layering */
356
357 mits = minor_iterations;
358 while (major_iterations-- > 0)
359 {
360 if (verbosity > silent)
361 PR_fprintf(logFile, "Beginning non-layered test\n");
362 client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
363 service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
364 rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
365 PR_ASSERT(PR_SUCCESS == rv);
366 rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
367 rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
368
369 minor_iterations = mits;
370 server_thread = PR_CreateThread(
371 PR_USER_THREAD, Server, service,
372 PR_PRIORITY_HIGH, thread_scope,
373 PR_JOINABLE_THREAD, 16 * 1024);
374 PR_ASSERT(NULL != server_thread);
375
376 client_thread = PR_CreateThread(
377 PR_USER_THREAD, Client, client,
378 PR_PRIORITY_NORMAL, thread_scope,
379 PR_JOINABLE_THREAD, 16 * 1024);
380 PR_ASSERT(NULL != client_thread);
381
382 rv = PR_JoinThread(client_thread);
383 PR_ASSERT(PR_SUCCESS == rv);
384 rv = PR_JoinThread(server_thread);
385 PR_ASSERT(PR_SUCCESS == rv);
386
387 rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
388 rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
389 if (verbosity > silent)
390 PR_fprintf(logFile, "Ending non-layered test\n");
391
392 /* with layering */
393 if (verbosity > silent)
394 PR_fprintf(logFile, "Beginning layered test\n");
395 client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
396 PushLayer(client);
397 service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
398 PushLayer(service);
399 rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
400 PR_ASSERT(PR_SUCCESS == rv);
401 rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
402 rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
403
404 minor_iterations = mits;
405 server_thread = PR_CreateThread(
406 PR_USER_THREAD, Server, service,
407 PR_PRIORITY_HIGH, thread_scope,
408 PR_JOINABLE_THREAD, 16 * 1024);
409 PR_ASSERT(NULL != server_thread);
410
411 client_thread = PR_CreateThread(
412 PR_USER_THREAD, Client, client,
413 PR_PRIORITY_NORMAL, thread_scope,
414 PR_JOINABLE_THREAD, 16 * 1024);
415 PR_ASSERT(NULL != client_thread);
416
417 rv = PR_JoinThread(client_thread);
418 PR_ASSERT(PR_SUCCESS == rv);
419 rv = PR_JoinThread(server_thread);
420 PR_ASSERT(PR_SUCCESS == rv);
421
422 rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
423 rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
424 /* with layering, using new style stack */
425 if (verbosity > silent)
426 PR_fprintf(logFile,
427 "Beginning layered test with new style stack\n");
428 client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
429 client_stack = PR_CreateIOLayer(client);
430 PushNewLayers(client_stack);
431 service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
432 service_stack = PR_CreateIOLayer(service);
433 PushNewLayers(service_stack);
434 rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
435 PR_ASSERT(PR_SUCCESS == rv);
436 rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
437 rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
438
439 minor_iterations = mits;
440 server_thread = PR_CreateThread(
441 PR_USER_THREAD, Server, service_stack,
442 PR_PRIORITY_HIGH, thread_scope,
443 PR_JOINABLE_THREAD, 16 * 1024);
444 PR_ASSERT(NULL != server_thread);
445
446 client_thread = PR_CreateThread(
447 PR_USER_THREAD, Client, client_stack,
448 PR_PRIORITY_NORMAL, thread_scope,
449 PR_JOINABLE_THREAD, 16 * 1024);
450 PR_ASSERT(NULL != client_thread);
451
452 rv = PR_JoinThread(client_thread);
453 PR_ASSERT(PR_SUCCESS == rv);
454 rv = PR_JoinThread(server_thread);
455 PR_ASSERT(PR_SUCCESS == rv);
456
457 rv = PR_Close(client_stack); PR_ASSERT(PR_SUCCESS == rv);
458 rv = PR_Close(service_stack); PR_ASSERT(PR_SUCCESS == rv);
459 if (verbosity > silent)
460 PR_fprintf(logFile, "Ending layered test\n");
461 }
462 return 0;
463} /* main */
464
465/* layer.c */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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