nsprpub/pr/tests/acceptread.c

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

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

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include <prio.h>
michael@0 7 #include <prprf.h>
michael@0 8 #include <prinit.h>
michael@0 9 #include <prnetdb.h>
michael@0 10 #include <prinrval.h>
michael@0 11 #include <prthread.h>
michael@0 12
michael@0 13 #include <plerror.h>
michael@0 14
michael@0 15 #include <stdlib.h>
michael@0 16
michael@0 17 #define DEFAULT_PORT 12273
michael@0 18 #define GET "GET / HTTP/1.0\n\n"
michael@0 19 static PRFileDesc *std_out, *err_out;
michael@0 20 static PRIntervalTime write_dally, accept_timeout;
michael@0 21
michael@0 22 static PRStatus PrintAddress(const PRNetAddr* address)
michael@0 23 {
michael@0 24 char buffer[100];
michael@0 25 PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
michael@0 26 if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString");
michael@0 27 else PR_fprintf(
michael@0 28 std_out, "Accepted connection from (0x%p)%s:%d\n",
michael@0 29 address, buffer, address->inet.port);
michael@0 30 return rv;
michael@0 31 } /* PrintAddress */
michael@0 32
michael@0 33 static void ConnectingThread(void *arg)
michael@0 34 {
michael@0 35 PRInt32 nbytes;
michael@0 36 #ifdef SYMBIAN
michael@0 37 char buf[256];
michael@0 38 #else
michael@0 39 char buf[1024];
michael@0 40 #endif
michael@0 41 PRFileDesc *sock;
michael@0 42 PRNetAddr peer_addr, *addr;
michael@0 43
michael@0 44 addr = (PRNetAddr*)arg;
michael@0 45
michael@0 46 sock = PR_NewTCPSocket();
michael@0 47 if (sock == NULL)
michael@0 48 {
michael@0 49 PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
michael@0 50 PR_ProcessExit(1);
michael@0 51 }
michael@0 52
michael@0 53 if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
michael@0 54 {
michael@0 55 PL_FPrintError(err_out, "PR_Connect (client) failed");
michael@0 56 PR_ProcessExit(1);
michael@0 57 }
michael@0 58 if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
michael@0 59 {
michael@0 60 PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
michael@0 61 PR_ProcessExit(1);
michael@0 62 }
michael@0 63
michael@0 64 /*
michael@0 65 ** Then wait between the connection coming up and sending the expected
michael@0 66 ** data. At some point in time, the server should fail due to a timeou
michael@0 67 ** on the AcceptRead() operation, which according to the document is
michael@0 68 ** only due to the read() portion.
michael@0 69 */
michael@0 70 PR_Sleep(write_dally);
michael@0 71
michael@0 72 nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
michael@0 73 if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");
michael@0 74
michael@0 75 nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
michael@0 76 if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
michael@0 77 else
michael@0 78 {
michael@0 79 PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
michael@0 80 buf[sizeof(buf) - 1] = '\0';
michael@0 81 PR_fprintf(std_out, "%s\n", buf);
michael@0 82 }
michael@0 83
michael@0 84 if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
michael@0 85 PL_FPrintError(err_out, "PR_Shutdown (client) failed");
michael@0 86
michael@0 87 if (PR_FAILURE == PR_Close(sock))
michael@0 88 PL_FPrintError(err_out, "PR_Close (client) failed");
michael@0 89
michael@0 90 return;
michael@0 91 } /* ConnectingThread */
michael@0 92
michael@0 93 #define BUF_SIZE 117
michael@0 94 static void AcceptingThread(void *arg)
michael@0 95 {
michael@0 96 PRStatus rv;
michael@0 97 PRInt32 bytes;
michael@0 98 PRSize buf_size = BUF_SIZE;
michael@0 99 PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
michael@0 100 PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
michael@0 101 PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
michael@0 102 PRSocketOptionData sock_opt;
michael@0 103
michael@0 104 if (NULL == listen_sock)
michael@0 105 {
michael@0 106 PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
michael@0 107 PR_ProcessExit(1);
michael@0 108 }
michael@0 109 sock_opt.option = PR_SockOpt_Reuseaddr;
michael@0 110 sock_opt.value.reuse_addr = PR_TRUE;
michael@0 111 rv = PR_SetSocketOption(listen_sock, &sock_opt);
michael@0 112 if (PR_FAILURE == rv)
michael@0 113 {
michael@0 114 PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
michael@0 115 PR_ProcessExit(1);
michael@0 116 }
michael@0 117 rv = PR_Bind(listen_sock, listen_addr);
michael@0 118 if (PR_FAILURE == rv)
michael@0 119 {
michael@0 120 PL_FPrintError(err_out, "PR_Bind (server) failed");
michael@0 121 PR_ProcessExit(1);
michael@0 122 }
michael@0 123 rv = PR_Listen(listen_sock, 10);
michael@0 124 if (PR_FAILURE == rv)
michael@0 125 {
michael@0 126 PL_FPrintError(err_out, "PR_Listen (server) failed");
michael@0 127 PR_ProcessExit(1);
michael@0 128 }
michael@0 129 bytes = PR_AcceptRead(
michael@0 130 listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);
michael@0 131
michael@0 132 if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
michael@0 133 else
michael@0 134 {
michael@0 135 PrintAddress(accept_addr);
michael@0 136 PR_fprintf(
michael@0 137 std_out, "(Server) read [0x%p..0x%p) %s\n",
michael@0 138 buf, &buf[BUF_SIZE], buf);
michael@0 139 bytes = PR_Write(accept_sock, buf, bytes);
michael@0 140 rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
michael@0 141 if (PR_FAILURE == rv)
michael@0 142 PL_FPrintError(err_out, "PR_Shutdown (server) failed");
michael@0 143 }
michael@0 144
michael@0 145 if (-1 != bytes)
michael@0 146 {
michael@0 147 rv = PR_Close(accept_sock);
michael@0 148 if (PR_FAILURE == rv)
michael@0 149 PL_FPrintError(err_out, "PR_Close (server) failed");
michael@0 150 }
michael@0 151
michael@0 152 rv = PR_Close(listen_sock);
michael@0 153 if (PR_FAILURE == rv)
michael@0 154 PL_FPrintError(err_out, "PR_Close (server) failed");
michael@0 155 } /* AcceptingThread */
michael@0 156
michael@0 157 int main(int argc, char **argv)
michael@0 158 {
michael@0 159 PRHostEnt he;
michael@0 160 PRStatus status;
michael@0 161 PRIntn next_index;
michael@0 162 PRUint16 port_number;
michael@0 163 char netdb_buf[PR_NETDB_BUF_SIZE];
michael@0 164 PRNetAddr client_addr, server_addr;
michael@0 165 PRThread *client_thread, *server_thread;
michael@0 166 PRIntervalTime delta = PR_MillisecondsToInterval(500);
michael@0 167
michael@0 168 err_out = PR_STDERR;
michael@0 169 std_out = PR_STDOUT;
michael@0 170 accept_timeout = PR_SecondsToInterval(2);
michael@0 171
michael@0 172 if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
michael@0 173 else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);
michael@0 174
michael@0 175 status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
michael@0 176 if (PR_SUCCESS != status)
michael@0 177 {
michael@0 178 PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
michael@0 179 PR_ProcessExit(1);
michael@0 180 }
michael@0 181 if (argc < 3)
michael@0 182 {
michael@0 183 status = PR_InitializeNetAddr(
michael@0 184 PR_IpAddrLoopback, port_number, &client_addr);
michael@0 185 if (PR_SUCCESS != status)
michael@0 186 {
michael@0 187 PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
michael@0 188 PR_ProcessExit(1);
michael@0 189 }
michael@0 190 }
michael@0 191 else
michael@0 192 {
michael@0 193 status = PR_GetHostByName(
michael@0 194 argv[1], netdb_buf, sizeof(netdb_buf), &he);
michael@0 195 if (status == PR_FAILURE)
michael@0 196 {
michael@0 197 PL_FPrintError(err_out, "PR_GetHostByName failed");
michael@0 198 PR_ProcessExit(1);
michael@0 199 }
michael@0 200 next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
michael@0 201 if (next_index == -1)
michael@0 202 {
michael@0 203 PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
michael@0 204 PR_ProcessExit(1);
michael@0 205 }
michael@0 206 }
michael@0 207
michael@0 208 for (
michael@0 209 write_dally = 0;
michael@0 210 write_dally < accept_timeout + (2 * delta);
michael@0 211 write_dally += delta)
michael@0 212 {
michael@0 213 PR_fprintf(
michael@0 214 std_out, "Testing w/ write_dally = %d msec\n",
michael@0 215 PR_IntervalToMilliseconds(write_dally));
michael@0 216 server_thread = PR_CreateThread(
michael@0 217 PR_USER_THREAD, AcceptingThread, &server_addr,
michael@0 218 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 219 if (server_thread == NULL)
michael@0 220 {
michael@0 221 PL_FPrintError(err_out, "PR_CreateThread (server) failed");
michael@0 222 PR_ProcessExit(1);
michael@0 223 }
michael@0 224
michael@0 225 PR_Sleep(delta); /* let the server pot thicken */
michael@0 226
michael@0 227 client_thread = PR_CreateThread(
michael@0 228 PR_USER_THREAD, ConnectingThread, &client_addr,
michael@0 229 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 230 if (client_thread == NULL)
michael@0 231 {
michael@0 232 PL_FPrintError(err_out, "PR_CreateThread (client) failed");
michael@0 233 PR_ProcessExit(1);
michael@0 234 }
michael@0 235
michael@0 236 if (PR_JoinThread(client_thread) == PR_FAILURE)
michael@0 237 PL_FPrintError(err_out, "PR_JoinThread (client) failed");
michael@0 238
michael@0 239 if (PR_JoinThread(server_thread) == PR_FAILURE)
michael@0 240 PL_FPrintError(err_out, "PR_JoinThread (server) failed");
michael@0 241 }
michael@0 242
michael@0 243 return 0;
michael@0 244 }

mercurial