nsprpub/pr/tests/tmocon.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

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 /***********************************************************************
michael@0 7 **
michael@0 8 ** Name: tmocon.c
michael@0 9 **
michael@0 10 ** Description: test client socket connection.
michael@0 11 **
michael@0 12 ** Modification History:
michael@0 13 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
michael@0 14 ** The debug mode will print all of the printfs associated with this test.
michael@0 15 ** The regress mode will be the default mode. Since the regress tool limits
michael@0 16 ** the output to a one line status:PASS or FAIL,all of the printf statements
michael@0 17 ** have been handled with an if (debug_mode) statement.
michael@0 18 ***********************************************************************/
michael@0 19
michael@0 20 /***********************************************************************
michael@0 21 ** Includes
michael@0 22 ***********************************************************************/
michael@0 23 /* Used to get the command line option */
michael@0 24 #include "plgetopt.h"
michael@0 25
michael@0 26 #include "nspr.h"
michael@0 27 #include "pprio.h"
michael@0 28
michael@0 29 #include "plerror.h"
michael@0 30 #include "plgetopt.h"
michael@0 31
michael@0 32 #include <stdio.h>
michael@0 33 #include <stdlib.h>
michael@0 34 #include <string.h>
michael@0 35
michael@0 36 /* for getcwd */
michael@0 37 #if defined(XP_UNIX) || defined (XP_OS2) || defined(XP_BEOS)
michael@0 38 #include <unistd.h>
michael@0 39 #elif defined(XP_PC)
michael@0 40 #include <direct.h>
michael@0 41 #endif
michael@0 42
michael@0 43 #ifdef WINCE
michael@0 44 #include <windows.h>
michael@0 45 char *getcwd(char *buf, size_t size)
michael@0 46 {
michael@0 47 wchar_t wpath[MAX_PATH];
michael@0 48 _wgetcwd(wpath, MAX_PATH);
michael@0 49 WideCharToMultiByte(CP_ACP, 0, wpath, -1, buf, size, 0, 0);
michael@0 50 }
michael@0 51 #endif
michael@0 52
michael@0 53 #define BASE_PORT 9867
michael@0 54
michael@0 55 #define DEFAULT_DALLY 1
michael@0 56 #define DEFAULT_THREADS 1
michael@0 57 #define DEFAULT_TIMEOUT 10
michael@0 58 #define DEFAULT_MESSAGES 100
michael@0 59 #define DEFAULT_MESSAGESIZE 100
michael@0 60
michael@0 61 static PRFileDesc *debug_out = NULL;
michael@0 62
michael@0 63 typedef struct Shared
michael@0 64 {
michael@0 65 PRBool random;
michael@0 66 PRBool failed;
michael@0 67 PRBool intermittant;
michael@0 68 PRIntn debug;
michael@0 69 PRInt32 messages;
michael@0 70 PRIntervalTime dally;
michael@0 71 PRIntervalTime timeout;
michael@0 72 PRInt32 message_length;
michael@0 73 PRNetAddr serverAddress;
michael@0 74 } Shared;
michael@0 75
michael@0 76 static PRIntervalTime Timeout(const Shared *shared)
michael@0 77 {
michael@0 78 PRIntervalTime timeout = shared->timeout;
michael@0 79 if (shared->random)
michael@0 80 {
michael@0 81 PRIntervalTime quarter = timeout >> 2; /* one quarter of the interval */
michael@0 82 PRUint32 random = rand() % quarter; /* something in[0..timeout / 4) */
michael@0 83 timeout = (((3 * quarter) + random) >> 2) + quarter; /* [75..125)% */
michael@0 84 }
michael@0 85 return timeout;
michael@0 86 } /* Timeout */
michael@0 87
michael@0 88 static void CauseTimeout(const Shared *shared)
michael@0 89 {
michael@0 90 if (shared->intermittant) PR_Sleep(Timeout(shared));
michael@0 91 } /* CauseTimeout */
michael@0 92
michael@0 93 static PRStatus MakeReceiver(Shared *shared)
michael@0 94 {
michael@0 95 PRStatus rv = PR_FAILURE;
michael@0 96 if (PR_IsNetAddrType(&shared->serverAddress, PR_IpAddrLoopback))
michael@0 97 {
michael@0 98 char *argv[3];
michael@0 99 char path[1024 + sizeof("/tmoacc")];
michael@0 100
michael@0 101 getcwd(path, sizeof(path));
michael@0 102
michael@0 103 (void)strcat(path, "/tmoacc");
michael@0 104 #ifdef XP_PC
michael@0 105 (void)strcat(path, ".exe");
michael@0 106 #endif
michael@0 107 argv[0] = path;
michael@0 108 if (shared->debug > 0)
michael@0 109 {
michael@0 110 argv[1] = "-d";
michael@0 111 argv[2] = NULL;
michael@0 112 }
michael@0 113 else argv[1] = NULL;
michael@0 114 if (shared->debug > 1)
michael@0 115 PR_fprintf(debug_out, " creating accept process %s ...", path);
michael@0 116 fflush(stdout);
michael@0 117 rv = PR_CreateProcessDetached(path, argv, NULL, NULL);
michael@0 118 if (PR_SUCCESS == rv)
michael@0 119 {
michael@0 120 if (shared->debug > 1)
michael@0 121 PR_fprintf(debug_out, " wait 5 seconds");
michael@0 122 if (shared->debug > 1)
michael@0 123 PR_fprintf(debug_out, " before connecting to accept process ...");
michael@0 124 fflush(stdout);
michael@0 125 PR_Sleep(PR_SecondsToInterval(5));
michael@0 126 return rv;
michael@0 127 }
michael@0 128 shared->failed = PR_TRUE;
michael@0 129 if (shared->debug > 0)
michael@0 130 PL_FPrintError(debug_out, "PR_CreateProcessDetached failed");
michael@0 131 }
michael@0 132 return rv;
michael@0 133 } /* MakeReceiver */
michael@0 134
michael@0 135 static void Connect(void *arg)
michael@0 136 {
michael@0 137 PRStatus rv;
michael@0 138 char *buffer = NULL;
michael@0 139 PRFileDesc *clientSock;
michael@0 140 Shared *shared = (Shared*)arg;
michael@0 141 PRInt32 loop, bytes, flags = 0;
michael@0 142 struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor;
michael@0 143 debug_out = (0 == shared->debug) ? NULL : PR_GetSpecialFD(PR_StandardError);
michael@0 144
michael@0 145 buffer = (char*)PR_MALLOC(shared->message_length);
michael@0 146
michael@0 147 for (bytes = 0; bytes < shared->message_length; ++bytes)
michael@0 148 buffer[bytes] = (char)bytes;
michael@0 149
michael@0 150 descriptor.checksum = 0;
michael@0 151 for (bytes = 0; bytes < shared->message_length; ++bytes)
michael@0 152 {
michael@0 153 PRUint32 overflow = descriptor.checksum & 0x80000000;
michael@0 154 descriptor.checksum = (descriptor.checksum << 1);
michael@0 155 if (0x00000000 != overflow) descriptor.checksum += 1;
michael@0 156 descriptor.checksum += buffer[bytes];
michael@0 157 }
michael@0 158 descriptor.checksum = PR_htonl(descriptor.checksum);
michael@0 159
michael@0 160 for (loop = 0; loop < shared->messages; ++loop)
michael@0 161 {
michael@0 162 if (shared->debug > 1)
michael@0 163 PR_fprintf(debug_out, "[%d]socket ... ", loop);
michael@0 164 clientSock = PR_NewTCPSocket();
michael@0 165 if (clientSock)
michael@0 166 {
michael@0 167 /*
michael@0 168 * We need to slow down the rate of generating connect requests,
michael@0 169 * otherwise the listen backlog queue on the accept side may
michael@0 170 * become full and we will get connection refused or timeout
michael@0 171 * error.
michael@0 172 */
michael@0 173
michael@0 174 PR_Sleep(shared->dally);
michael@0 175 if (shared->debug > 1)
michael@0 176 {
michael@0 177 char buf[128];
michael@0 178 PR_NetAddrToString(&shared->serverAddress, buf, sizeof(buf));
michael@0 179 PR_fprintf(debug_out, "connecting to %s ... ", buf);
michael@0 180 }
michael@0 181 rv = PR_Connect(
michael@0 182 clientSock, &shared->serverAddress, Timeout(shared));
michael@0 183 if (PR_SUCCESS == rv)
michael@0 184 {
michael@0 185 PRInt32 descriptor_length = (loop < (shared->messages - 1)) ?
michael@0 186 shared->message_length : 0;
michael@0 187 descriptor.length = PR_htonl(descriptor_length);
michael@0 188 if (shared->debug > 1)
michael@0 189 PR_fprintf(
michael@0 190 debug_out, "sending %d bytes ... ", descriptor_length);
michael@0 191 CauseTimeout(shared); /* might cause server to timeout */
michael@0 192 bytes = PR_Send(
michael@0 193 clientSock, &descriptor, sizeof(descriptor),
michael@0 194 flags, Timeout(shared));
michael@0 195 if (bytes != sizeof(descriptor))
michael@0 196 {
michael@0 197 shared->failed = PR_TRUE;
michael@0 198 if (shared->debug > 0)
michael@0 199 PL_FPrintError(debug_out, "PR_Send failed");
michael@0 200 }
michael@0 201 if (0 != descriptor_length)
michael@0 202 {
michael@0 203 CauseTimeout(shared);
michael@0 204 bytes = PR_Send(
michael@0 205 clientSock, buffer, descriptor_length,
michael@0 206 flags, Timeout(shared));
michael@0 207 if (bytes != descriptor_length)
michael@0 208 {
michael@0 209 shared->failed = PR_TRUE;
michael@0 210 if (shared->debug > 0)
michael@0 211 PL_FPrintError(debug_out, "PR_Send failed");
michael@0 212 }
michael@0 213 }
michael@0 214 if (shared->debug > 1) PR_fprintf(debug_out, "closing ... ");
michael@0 215 rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
michael@0 216 rv = PR_Close(clientSock);
michael@0 217 if (shared->debug > 1)
michael@0 218 {
michael@0 219 if (PR_SUCCESS == rv) PR_fprintf(debug_out, "\n");
michael@0 220 else PL_FPrintError(debug_out, "shutdown failed");
michael@0 221 }
michael@0 222 }
michael@0 223 else
michael@0 224 {
michael@0 225 if (shared->debug > 1) PL_FPrintError(debug_out, "connect failed");
michael@0 226 PR_Close(clientSock);
michael@0 227 if ((loop == 0) && (PR_GetError() == PR_CONNECT_REFUSED_ERROR))
michael@0 228 {
michael@0 229 if (MakeReceiver(shared) == PR_FAILURE) break;
michael@0 230 }
michael@0 231 else
michael@0 232 {
michael@0 233 if (shared->debug > 1) PR_fprintf(debug_out, " exiting\n");
michael@0 234 break;
michael@0 235 }
michael@0 236 }
michael@0 237 }
michael@0 238 else
michael@0 239 {
michael@0 240 shared->failed = PR_TRUE;
michael@0 241 if (shared->debug > 0) PL_FPrintError(debug_out, "create socket");
michael@0 242 break;
michael@0 243 }
michael@0 244 }
michael@0 245
michael@0 246 PR_DELETE(buffer);
michael@0 247 } /* Connect */
michael@0 248
michael@0 249 int Tmocon(int argc, char **argv)
michael@0 250 {
michael@0 251 /*
michael@0 252 * USAGE
michael@0 253 * -d turn on debugging output (default = off)
michael@0 254 * -v turn on verbose output (default = off)
michael@0 255 * -h <n> dns name of host serving the connection (default = self)
michael@0 256 * -i dally intermittantly to cause timeouts (default = off)
michael@0 257 * -m <n> number of messages to send (default = 100)
michael@0 258 * -s <n> size of each message (default = 100)
michael@0 259 * -t <n> number of threads sending (default = 1)
michael@0 260 * -G use global threads (default = local)
michael@0 261 * -T <n> timeout on I/O operations (seconds) (default = 10)
michael@0 262 * -D <n> dally between connect requests (seconds)(default = 0)
michael@0 263 * -R randomize the dally types around 'T' (default = no)
michael@0 264 */
michael@0 265
michael@0 266 PRStatus rv;
michael@0 267 int exitStatus;
michael@0 268 PLOptStatus os;
michael@0 269 Shared *shared = NULL;
michael@0 270 PRThread **thread = NULL;
michael@0 271 PRIntn index, threads = DEFAULT_THREADS;
michael@0 272 PRThreadScope thread_scope = PR_LOCAL_THREAD;
michael@0 273 PRInt32 dally = DEFAULT_DALLY, timeout = DEFAULT_TIMEOUT;
michael@0 274 PLOptState *opt = PL_CreateOptState(argc, argv, "divGRh:m:s:t:T:D:");
michael@0 275
michael@0 276 shared = PR_NEWZAP(Shared);
michael@0 277
michael@0 278 shared->debug = 0;
michael@0 279 shared->failed = PR_FALSE;
michael@0 280 shared->random = PR_FALSE;
michael@0 281 shared->messages = DEFAULT_MESSAGES;
michael@0 282 shared->message_length = DEFAULT_MESSAGESIZE;
michael@0 283
michael@0 284 PR_STDIO_INIT();
michael@0 285 memset(&shared->serverAddress, 0, sizeof(shared->serverAddress));
michael@0 286 rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &shared->serverAddress);
michael@0 287 PR_ASSERT(PR_SUCCESS == rv);
michael@0 288
michael@0 289 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 290 {
michael@0 291 if (PL_OPT_BAD == os) continue;
michael@0 292 switch (opt->option)
michael@0 293 {
michael@0 294 case 'd':
michael@0 295 if (0 == shared->debug) shared->debug = 1;
michael@0 296 break;
michael@0 297 case 'v':
michael@0 298 if (0 == shared->debug) shared->debug = 2;
michael@0 299 break;
michael@0 300 case 'i':
michael@0 301 shared->intermittant = PR_TRUE;
michael@0 302 break;
michael@0 303 case 'R':
michael@0 304 shared->random = PR_TRUE;
michael@0 305 break;
michael@0 306 case 'G':
michael@0 307 thread_scope = PR_GLOBAL_THREAD;
michael@0 308 break;
michael@0 309 case 'h': /* the value for backlock */
michael@0 310 {
michael@0 311 PRIntn es = 0;
michael@0 312 PRHostEnt host;
michael@0 313 char buffer[1024];
michael@0 314 (void)PR_GetHostByName(
michael@0 315 opt->value, buffer, sizeof(buffer), &host);
michael@0 316 es = PR_EnumerateHostEnt(
michael@0 317 es, &host, BASE_PORT, &shared->serverAddress);
michael@0 318 PR_ASSERT(es > 0);
michael@0 319 }
michael@0 320 break;
michael@0 321 case 'm': /* number of messages to send */
michael@0 322 shared->messages = atoi(opt->value);
michael@0 323 break;
michael@0 324 case 't': /* number of threads sending */
michael@0 325 threads = atoi(opt->value);
michael@0 326 break;
michael@0 327 case 'D': /* dally time between transmissions */
michael@0 328 dally = atoi(opt->value);
michael@0 329 break;
michael@0 330 case 'T': /* timeout on I/O operations */
michael@0 331 timeout = atoi(opt->value);
michael@0 332 break;
michael@0 333 case 's': /* total size of each message */
michael@0 334 shared->message_length = atoi(opt->value);
michael@0 335 break;
michael@0 336 default:
michael@0 337 break;
michael@0 338 }
michael@0 339 }
michael@0 340 PL_DestroyOptState(opt);
michael@0 341
michael@0 342 if (0 == timeout) timeout = DEFAULT_TIMEOUT;
michael@0 343 if (0 == threads) threads = DEFAULT_THREADS;
michael@0 344 if (0 == shared->messages) shared->messages = DEFAULT_MESSAGES;
michael@0 345 if (0 == shared->message_length) shared->message_length = DEFAULT_MESSAGESIZE;
michael@0 346
michael@0 347 shared->dally = PR_SecondsToInterval(dally);
michael@0 348 shared->timeout = PR_SecondsToInterval(timeout);
michael@0 349
michael@0 350 thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*));
michael@0 351
michael@0 352 for (index = 0; index < threads; ++index)
michael@0 353 thread[index] = PR_CreateThread(
michael@0 354 PR_USER_THREAD, Connect, shared,
michael@0 355 PR_PRIORITY_NORMAL, thread_scope,
michael@0 356 PR_JOINABLE_THREAD, 0);
michael@0 357 for (index = 0; index < threads; ++index)
michael@0 358 rv = PR_JoinThread(thread[index]);
michael@0 359
michael@0 360 PR_DELETE(thread);
michael@0 361
michael@0 362 PR_fprintf(
michael@0 363 PR_GetSpecialFD(PR_StandardError), "%s\n",
michael@0 364 ((shared->failed) ? "FAILED" : "PASSED"));
michael@0 365 exitStatus = (shared->failed) ? 1 : 0;
michael@0 366 PR_DELETE(shared);
michael@0 367 return exitStatus;
michael@0 368 }
michael@0 369
michael@0 370 int main(int argc, char **argv)
michael@0 371 {
michael@0 372 return (PR_VersionCheck(PR_VERSION)) ?
michael@0 373 PR_Initialize(Tmocon, argc, argv, 4) : -1;
michael@0 374 } /* main */
michael@0 375
michael@0 376 /* tmocon.c */
michael@0 377
michael@0 378

mercurial