~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/libs/xpcom18a4/nsprpub/pr/tests/layer.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
63
static PRFileDesc *logFile;
 
64
static PRDescIdentity identity;
 
65
static PRNetAddr server_address;
 
66
 
 
67
static PRIOMethods myMethods;
 
68
 
 
69
typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
 
70
 
 
71
static PRIntn minor_iterations = 5;
 
72
static PRIntn major_iterations = 1;
 
73
static Verbosity verbosity = quiet;
 
74
static PRUint16 default_port = 12273;
 
75
 
 
76
static 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
 
 
86
static 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
 
121
static 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
 
 
132
static 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
 
 
165
static 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
 
 
204
static 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
 
 
239
static 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
 
 
273
static 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
 
 
281
PRIntn 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 */