home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / tests / layer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  9.6 KB  |  290 lines

  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 Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "prio.h"
  20. #include "prprf.h"
  21. #include "prlog.h"
  22. #include "prnetdb.h"
  23. #include "prthread.h"
  24.  
  25. #include "plerror.h"
  26. #include "plgetopt.h"
  27. #include "prwin16.h"
  28.  
  29. #include <stdlib.h>
  30.  
  31. /*
  32. ** Testing layering of I/O
  33. **
  34. **      The layered server
  35. ** A thread that acts as a server. It creates a TCP listener with a dummy
  36. ** layer pushed on top. Then listens for incoming connections. Each connection
  37. ** request for connection will be layered as well, accept one request, echo
  38. ** it back and close.
  39. **
  40. **      The layered client
  41. ** Pretty much what you'd expect.
  42. */
  43.  
  44. static PRFileDesc *logFile;
  45. static PRDescIdentity identity;
  46. static PRNetAddr server_address;
  47.  
  48. static PRIOMethods myMethods;
  49.  
  50. typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
  51.  
  52. static PRIntn minor_iterations = 5;
  53. static PRIntn major_iterations = 1;
  54. static Verbosity verbosity = quiet;
  55. static PRUint16 default_port = 12273;
  56.  
  57. static PRFileDesc *PushLayer(PRFileDesc *stack)
  58. {
  59.     PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods);
  60.     PRStatus rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
  61.     if (verbosity > quiet)
  62.         PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack);
  63.     PR_ASSERT(PR_SUCCESS == rv);
  64.     return layer;
  65. }  /* PushLayer */
  66.  
  67. static PRFileDesc *PopLayer(PRFileDesc *stack)
  68. {
  69.     PRFileDesc *popped = PR_PopIOLayer(stack, identity);
  70.     if (verbosity > quiet)
  71.         PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack);
  72.     popped->dtor(popped);
  73.     
  74.     return stack;
  75. }  /* PopLayer */
  76.  
  77. static void PR_CALLBACK Client(void *arg)
  78. {
  79.     PRStatus rv;
  80.     PRUint8 buffer[100];
  81.     PRIntn empty_flags = 0;
  82.     PRIntn bytes_read, bytes_sent;
  83.     PRFileDesc *stack = (PRFileDesc*)arg;
  84.  
  85.     rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
  86.     PR_ASSERT(PR_SUCCESS == rv);
  87.     while (minor_iterations-- > 0)
  88.     {
  89.         bytes_sent = PR_Send(
  90.             stack, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
  91.         PR_ASSERT(sizeof(buffer) == bytes_sent);
  92.         if (verbosity > chatty)
  93.             PR_fprintf(logFile, "Client sending %d bytes\n", bytes_sent);
  94.         bytes_read = PR_Recv(
  95.             stack, buffer, bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT);
  96.         if (verbosity > chatty)
  97.             PR_fprintf(logFile, "Client receiving %d bytes\n", bytes_read);
  98.         PR_ASSERT(bytes_read == bytes_sent);
  99.     }
  100.  
  101.     if (verbosity > quiet)
  102.         PR_fprintf(logFile, "Client shutting down stack\n");
  103.     
  104.     rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
  105. }  /* Client */
  106.  
  107. static void PR_CALLBACK Server(void *arg)
  108. {
  109.     PRStatus rv;
  110.     PRUint8 buffer[100];
  111.     PRFileDesc *service;
  112.     PRUintn empty_flags = 0;
  113.     PRIntn bytes_read, bytes_sent;
  114.     PRFileDesc *stack = (PRFileDesc*)arg;
  115.     PRNetAddr any_address, client_address;
  116.  
  117.     rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
  118.     PR_ASSERT(PR_SUCCESS == rv);
  119.  
  120.     rv = PR_Bind(stack, &any_address); PR_ASSERT(PR_SUCCESS == rv);
  121.     rv = PR_Listen(stack, 10); PR_ASSERT(PR_SUCCESS == rv);
  122.  
  123.     service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
  124.     if (verbosity > quiet)
  125.         PR_fprintf(logFile, "Server accepting connection\n");
  126.  
  127.     do
  128.     {
  129.         bytes_read = PR_Recv(
  130.             service, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
  131.         if (0 != bytes_read)
  132.         {
  133.             if (verbosity > chatty)
  134.                 PR_fprintf(logFile, "Server receiving %d bytes\n", bytes_read);
  135.             PR_ASSERT(bytes_read > 0);
  136.             bytes_sent = PR_Send(
  137.                 service, buffer, bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT);
  138.             if (verbosity > chatty)
  139.                 PR_fprintf(logFile, "Server sending %d bytes\n", bytes_sent);
  140.             PR_ASSERT(bytes_read == bytes_sent);
  141.         }
  142.  
  143.     } while (0 != bytes_read);
  144.  
  145.     if (verbosity > quiet)
  146.         PR_fprintf(logFile, "Server shutting down and closing stack\n");
  147.     rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
  148.     rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
  149.  
  150. }  /* Server */
  151.  
  152. static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
  153. {
  154.     PRIntn verbage = (PRIntn)verbosity;
  155.     return (Verbosity)(verbage + delta);
  156. }  /* ChangeVerbosity */
  157.  
  158. PRIntn main(PRIntn argc, char **argv)
  159. {
  160.     PRStatus rv;
  161.     PLOptStatus os;
  162.     PRFileDesc *client, *service;
  163.     const char *server_name = NULL;
  164.     PRIOMethods const *stubMethods;
  165.     PRThread *client_thread, *server_thread;
  166.     PRThreadScope thread_scope = PR_LOCAL_THREAD;
  167.     PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:");
  168.     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  169.     {
  170.         if (PL_OPT_BAD == os) continue;
  171.         switch (opt->option)
  172.         {
  173.         case 0:
  174.             server_name = opt->value;
  175.             break;
  176.         case 'd':  /* debug mode */
  177.             if (verbosity < noisy)
  178.                 verbosity = ChangeVerbosity(verbosity, 1);
  179.             break;
  180.         case 'q':  /* debug mode */
  181.             if (verbosity > silent)
  182.                 verbosity = ChangeVerbosity(verbosity, -1);
  183.             break;
  184.         case 'G':  /* use global threads */
  185.             thread_scope = PR_GLOBAL_THREAD;
  186.             break;
  187.         case 'C':  /* number of threads waiting */
  188.             major_iterations = atoi(opt->value);
  189.             break;
  190.         case 'c':  /* number of client threads */
  191.             minor_iterations = atoi(opt->value);
  192.             break;
  193.         case 'p':  /* default port */
  194.             default_port = atoi(opt->value);
  195.             break;
  196.         default:
  197.             break;
  198.         }
  199.     }
  200.     PL_DestroyOptState(opt);
  201.     PR_STDIO_INIT();
  202.  
  203.     logFile = PR_GetSpecialFD(PR_StandardError);
  204.  
  205.     identity = PR_GetUniqueIdentity("Dummy");
  206.     stubMethods = PR_GetDefaultIOMethods();
  207.  
  208.     /*
  209.     ** Normally here one would pick and choose between the default
  210.     ** stub methods and local, unique implmentation. I'm not going
  211.     ** quite that far.
  212.     */
  213.     myMethods = *stubMethods;
  214.  
  215.     if (NULL == server_name)
  216.         rv = PR_InitializeNetAddr(
  217.             PR_IpAddrLoopback, default_port, &server_address);
  218.     else
  219.     {
  220.         rv = PR_StringToNetAddr(server_name, &server_address);
  221.         PR_ASSERT(PR_SUCCESS == rv);
  222.         rv = PR_InitializeNetAddr(
  223.             PR_IpAddrNull, default_port, &server_address);
  224.     }
  225.     PR_ASSERT(PR_SUCCESS == rv);
  226.  
  227.     /* one type w/o layering */
  228.  
  229.     while (major_iterations-- > 0)
  230.     {
  231.         if (verbosity > silent)
  232.             PR_fprintf(logFile, "Beginning non-layered test\n");
  233.         client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
  234.         service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
  235.  
  236.         server_thread = PR_CreateThread(
  237.             PR_USER_THREAD, Server, service,
  238.             PR_PRIORITY_HIGH, thread_scope,
  239.             PR_JOINABLE_THREAD, 16 * 1024);
  240.         PR_ASSERT(NULL != server_thread);
  241.  
  242.         client_thread = PR_CreateThread(
  243.             PR_USER_THREAD, Client, client,
  244.             PR_PRIORITY_NORMAL, thread_scope,
  245.             PR_JOINABLE_THREAD, 16 * 1024);
  246.         PR_ASSERT(NULL != client_thread);
  247.  
  248.         rv = PR_JoinThread(client_thread);
  249.         PR_ASSERT(PR_SUCCESS == rv);
  250.         rv = PR_JoinThread(server_thread);
  251.         PR_ASSERT(PR_SUCCESS == rv);
  252.  
  253.         rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
  254.         rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
  255.         if (verbosity > silent)
  256.             PR_fprintf(logFile, "Ending non-layered test\n");
  257.  
  258.         /* with layering */
  259.         if (verbosity > silent)
  260.             PR_fprintf(logFile, "Beginning layered test\n");
  261.         client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
  262.         service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
  263.  
  264.         server_thread = PR_CreateThread(
  265.             PR_USER_THREAD, Server, PushLayer(service),
  266.             PR_PRIORITY_HIGH, thread_scope,
  267.             PR_JOINABLE_THREAD, 16 * 1024);
  268.         PR_ASSERT(NULL != server_thread);
  269.  
  270.         client_thread = PR_CreateThread(
  271.             PR_USER_THREAD, Client, PushLayer(client),
  272.             PR_PRIORITY_NORMAL, thread_scope,
  273.             PR_JOINABLE_THREAD, 16 * 1024);
  274.         PR_ASSERT(NULL != client_thread);
  275.  
  276.         rv = PR_JoinThread(client_thread);
  277.         PR_ASSERT(PR_SUCCESS == rv);
  278.         rv = PR_JoinThread(server_thread);
  279.         PR_ASSERT(PR_SUCCESS == rv);
  280.  
  281.         rv = PR_Close(PopLayer(client)); PR_ASSERT(PR_SUCCESS == rv);
  282.         rv = PR_Close(PopLayer(service)); PR_ASSERT(PR_SUCCESS == rv);
  283.         if (verbosity > silent)
  284.             PR_fprintf(logFile, "Ending layered test\n");
  285.     }
  286.     return 0;
  287. }  /* main */
  288.  
  289. /* layer.c */
  290.