nsprpub/pr/tests/acceptreademu.c

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     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 /*
     7  * This test is the same as acceptread.c except that it uses the
     8  * emulated acceptread method instead of the regular acceptread.
     9  */
    11 #include <prio.h>
    12 #include <prprf.h>
    13 #include <prinit.h>
    14 #include <prnetdb.h>
    15 #include <prinrval.h>
    16 #include <prthread.h>
    17 #include <pprio.h>
    19 #include <plerror.h>
    21 #include <stdlib.h>
    23 #define DEFAULT_PORT 12273
    24 #define GET "GET / HTTP/1.0\n\n"
    25 static PRFileDesc *std_out, *err_out;
    26 static PRIntervalTime write_dally, accept_timeout;
    27 static PRDescIdentity emu_layer_ident;
    28 static PRIOMethods emu_layer_methods;
    30 /* the acceptread method in emu_layer_methods */
    31 static PRInt32 PR_CALLBACK emu_AcceptRead(PRFileDesc *sd, PRFileDesc **nd,
    32     PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout)
    33 {
    34     return PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
    35 }
    37 static PRStatus PrintAddress(const PRNetAddr* address)
    38 {
    39     char buffer[100];
    40     PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
    41     if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString");
    42     else PR_fprintf(
    43         std_out, "Accepted connection from (0x%p)%s:%d\n",
    44         address, buffer, address->inet.port);
    45     return rv;
    46 }  /* PrintAddress */
    48 static void ConnectingThread(void *arg)
    49 {
    50     PRInt32 nbytes;
    51 #ifdef SYMBIAN
    52     char buf[256];
    53 #else
    54     char buf[1024];
    55 #endif
    56     PRFileDesc *sock;
    57     PRNetAddr peer_addr, *addr;
    59     addr = (PRNetAddr*)arg;
    61     sock = PR_NewTCPSocket();
    62     if (sock == NULL)
    63     {
    64         PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
    65         PR_ProcessExit(1);
    66     }
    68     if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
    69     {
    70         PL_FPrintError(err_out, "PR_Connect (client) failed");
    71         PR_ProcessExit(1);
    72     }
    73     if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
    74     {
    75         PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
    76         PR_ProcessExit(1);
    77     }
    79     /*
    80     ** Then wait between the connection coming up and sending the expected
    81     ** data. At some point in time, the server should fail due to a timeou
    82     ** on the AcceptRead() operation, which according to the document is
    83     ** only due to the read() portion.
    84     */
    85     PR_Sleep(write_dally);
    87     nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
    88     if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");
    90     nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
    91     if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
    92     else
    93     {
    94         PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
    95         buf[sizeof(buf) - 1] = '\0';
    96         PR_fprintf(std_out, "%s\n", buf);
    97     }
    99     if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
   100         PL_FPrintError(err_out, "PR_Shutdown (client) failed");
   102     if (PR_FAILURE == PR_Close(sock))
   103         PL_FPrintError(err_out, "PR_Close (client) failed");
   105     return;
   106 }  /* ConnectingThread */
   108 #define BUF_SIZE 117
   109 static void AcceptingThread(void *arg)
   110 {
   111     PRStatus rv;
   112     PRInt32 bytes;
   113     PRSize buf_size = BUF_SIZE;
   114     PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
   115     PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
   116     PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
   117     PRFileDesc *layer;
   118     PRSocketOptionData sock_opt;
   120     if (NULL == listen_sock)
   121     {
   122         PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
   123         PR_ProcessExit(1);        
   124     }
   125     layer = PR_CreateIOLayerStub(emu_layer_ident, &emu_layer_methods);
   126     if (NULL == layer)
   127     {
   128         PL_FPrintError(err_out, "PR_CreateIOLayerStub (server) failed");
   129         PR_ProcessExit(1);        
   130     }
   131     if (PR_PushIOLayer(listen_sock, PR_TOP_IO_LAYER, layer) == PR_FAILURE)
   132     {
   133         PL_FPrintError(err_out, "PR_PushIOLayer (server) failed");
   134         PR_ProcessExit(1);        
   135     }
   136     sock_opt.option = PR_SockOpt_Reuseaddr;
   137     sock_opt.value.reuse_addr = PR_TRUE;
   138     rv = PR_SetSocketOption(listen_sock, &sock_opt);
   139     if (PR_FAILURE == rv)
   140     {
   141         PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
   142         PR_ProcessExit(1);        
   143     }
   144     rv = PR_Bind(listen_sock, listen_addr);
   145     if (PR_FAILURE == rv)
   146     {
   147         PL_FPrintError(err_out, "PR_Bind (server) failed");
   148         PR_ProcessExit(1);        
   149     }
   150     rv = PR_Listen(listen_sock, 10);
   151     if (PR_FAILURE == rv)
   152     {
   153         PL_FPrintError(err_out, "PR_Listen (server) failed");
   154         PR_ProcessExit(1);        
   155     }
   156     bytes = PR_AcceptRead(
   157         listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);
   159     if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
   160     else
   161     {
   162         PrintAddress(accept_addr);
   163         PR_fprintf(
   164             std_out, "(Server) read [0x%p..0x%p) %s\n",
   165             buf, &buf[BUF_SIZE], buf);
   166         bytes = PR_Write(accept_sock, buf, bytes);
   167         rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
   168         if (PR_FAILURE == rv)
   169             PL_FPrintError(err_out, "PR_Shutdown (server) failed");
   170     }
   172     if (-1 != bytes)
   173     {
   174         rv = PR_Close(accept_sock);
   175         if (PR_FAILURE == rv)
   176             PL_FPrintError(err_out, "PR_Close (server) failed");
   177     }
   179     rv = PR_Close(listen_sock);
   180     if (PR_FAILURE == rv)
   181         PL_FPrintError(err_out, "PR_Close (server) failed");
   182 }  /* AcceptingThread */
   184 int main(int argc, char **argv)
   185 {
   186     PRHostEnt he;
   187     PRStatus status;
   188     PRIntn next_index;
   189     PRUint16 port_number;
   190     char netdb_buf[PR_NETDB_BUF_SIZE];
   191     PRNetAddr client_addr, server_addr;
   192     PRThread *client_thread, *server_thread;
   193     PRIntervalTime delta = PR_MillisecondsToInterval(500);
   195     err_out = PR_STDERR;
   196     std_out = PR_STDOUT;
   197     accept_timeout = PR_SecondsToInterval(2);
   198     emu_layer_ident = PR_GetUniqueIdentity("Emulated AcceptRead");
   199     emu_layer_methods = *PR_GetDefaultIOMethods();
   200     emu_layer_methods.acceptread = emu_AcceptRead;
   202     if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
   203     else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);
   205     status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
   206     if (PR_SUCCESS != status)
   207     {
   208         PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
   209         PR_ProcessExit(1);
   210     }
   211     if (argc < 3)
   212     {
   213         status = PR_InitializeNetAddr(
   214             PR_IpAddrLoopback, port_number, &client_addr);
   215         if (PR_SUCCESS != status)
   216         {
   217             PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
   218             PR_ProcessExit(1);
   219         }
   220     }
   221     else
   222     {
   223         status = PR_GetHostByName(
   224             argv[1], netdb_buf, sizeof(netdb_buf), &he);
   225         if (status == PR_FAILURE)
   226         {
   227             PL_FPrintError(err_out, "PR_GetHostByName failed");
   228             PR_ProcessExit(1);
   229         }
   230         next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
   231         if (next_index == -1)
   232         {
   233             PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
   234             PR_ProcessExit(1);
   235         }
   236     }
   238     for (
   239         write_dally = 0;
   240         write_dally < accept_timeout + (2 * delta);
   241         write_dally += delta)
   242     {
   243         PR_fprintf(
   244             std_out, "Testing w/ write_dally = %d msec\n",
   245             PR_IntervalToMilliseconds(write_dally));
   246         server_thread = PR_CreateThread(
   247             PR_USER_THREAD, AcceptingThread, &server_addr,
   248             PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
   249         if (server_thread == NULL)
   250         {
   251             PL_FPrintError(err_out, "PR_CreateThread (server) failed");
   252             PR_ProcessExit(1);
   253         }
   255         PR_Sleep(delta);  /* let the server pot thicken */
   257         client_thread = PR_CreateThread(
   258             PR_USER_THREAD, ConnectingThread, &client_addr,
   259             PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
   260         if (client_thread == NULL)
   261         {
   262             PL_FPrintError(err_out, "PR_CreateThread (client) failed");
   263             PR_ProcessExit(1);
   264         }
   266         if (PR_JoinThread(client_thread) == PR_FAILURE)
   267             PL_FPrintError(err_out, "PR_JoinThread (client) failed");
   269         if (PR_JoinThread(server_thread) == PR_FAILURE)
   270             PL_FPrintError(err_out, "PR_JoinThread (server) failed");
   271     }
   273     return 0;
   274 }

mercurial