~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/tests/layer.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

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