nsprpub/pr/tests/layer.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

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

mercurial