123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /***********************************************************************
- **
- ** Name: tmocon.c
- **
- ** Description: test client socket connection.
- **
- ** Modification History:
- ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
- ** The debug mode will print all of the printfs associated with this test.
- ** The regress mode will be the default mode. Since the regress tool limits
- ** the output to a one line status:PASS or FAIL,all of the printf statements
- ** have been handled with an if (debug_mode) statement.
- ***********************************************************************/
- /***********************************************************************
- ** Includes
- ***********************************************************************/
- /* Used to get the command line option */
- #include "plgetopt.h"
- #include "nspr.h"
- #include "pprio.h"
- #include "plerror.h"
- #include "plgetopt.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /* for getcwd */
- #if defined(XP_UNIX) || defined (XP_OS2)
- #include <unistd.h>
- #elif defined(XP_PC)
- #include <direct.h>
- #endif
- #ifdef WINCE
- #include <windows.h>
- char *getcwd(char *buf, size_t size)
- {
- wchar_t wpath[MAX_PATH];
- _wgetcwd(wpath, MAX_PATH);
- WideCharToMultiByte(CP_ACP, 0, wpath, -1, buf, size, 0, 0);
- }
- #endif
- #ifdef DEBUG
- #define PORT_INC_DO +100
- #else
- #define PORT_INC_DO
- #endif
- #ifdef IS_64
- #define PORT_INC_3264 +200
- #else
- #define PORT_INC_3264
- #endif
- #define BASE_PORT 9867 PORT_INC_DO PORT_INC_3264
- #define DEFAULT_DALLY 1
- #define DEFAULT_THREADS 1
- #define DEFAULT_TIMEOUT 10
- #define DEFAULT_MESSAGES 100
- #define DEFAULT_MESSAGESIZE 100
- static PRFileDesc *debug_out = NULL;
- typedef struct Shared
- {
- PRBool random;
- PRBool failed;
- PRBool intermittant;
- PRIntn debug;
- PRInt32 messages;
- PRIntervalTime dally;
- PRIntervalTime timeout;
- PRInt32 message_length;
- PRNetAddr serverAddress;
- } Shared;
- static PRIntervalTime Timeout(const Shared *shared)
- {
- PRIntervalTime timeout = shared->timeout;
- if (shared->random)
- {
- PRIntervalTime quarter = timeout >> 2; /* one quarter of the interval */
- PRUint32 random = rand() % quarter; /* something in[0..timeout / 4) */
- timeout = (((3 * quarter) + random) >> 2) + quarter; /* [75..125)% */
- }
- return timeout;
- } /* Timeout */
- static void CauseTimeout(const Shared *shared)
- {
- if (shared->intermittant) {
- PR_Sleep(Timeout(shared));
- }
- } /* CauseTimeout */
- static PRStatus MakeReceiver(Shared *shared)
- {
- PRStatus rv = PR_FAILURE;
- if (PR_IsNetAddrType(&shared->serverAddress, PR_IpAddrLoopback))
- {
- char *argv[3];
- char path[1024 + sizeof("/tmoacc")];
- getcwd(path, sizeof(path));
- (void)strcat(path, "/tmoacc");
- #ifdef XP_PC
- (void)strcat(path, ".exe");
- #endif
- argv[0] = path;
- if (shared->debug > 0)
- {
- argv[1] = "-d";
- argv[2] = NULL;
- }
- else {
- argv[1] = NULL;
- }
- if (shared->debug > 1) {
- PR_fprintf(debug_out, " creating accept process %s ...", path);
- }
- fflush(stdout);
- rv = PR_CreateProcessDetached(path, argv, NULL, NULL);
- if (PR_SUCCESS == rv)
- {
- if (shared->debug > 1) {
- PR_fprintf(debug_out, " wait 5 seconds");
- }
- if (shared->debug > 1) {
- PR_fprintf(debug_out, " before connecting to accept process ...");
- }
- fflush(stdout);
- PR_Sleep(PR_SecondsToInterval(5));
- return rv;
- }
- shared->failed = PR_TRUE;
- if (shared->debug > 0) {
- PL_FPrintError(debug_out, "PR_CreateProcessDetached failed");
- }
- }
- return rv;
- } /* MakeReceiver */
- static void Connect(void *arg)
- {
- PRStatus rv;
- char *buffer = NULL;
- PRFileDesc *clientSock;
- Shared *shared = (Shared*)arg;
- PRInt32 loop, bytes, flags = 0;
- struct Descriptor {
- PRInt32 length;
- PRUint32 checksum;
- } descriptor;
- debug_out = (0 == shared->debug) ? NULL : PR_GetSpecialFD(PR_StandardError);
- buffer = (char*)PR_MALLOC(shared->message_length);
- for (bytes = 0; bytes < shared->message_length; ++bytes) {
- buffer[bytes] = (char)bytes;
- }
- descriptor.checksum = 0;
- for (bytes = 0; bytes < shared->message_length; ++bytes)
- {
- PRUint32 overflow = descriptor.checksum & 0x80000000;
- descriptor.checksum = (descriptor.checksum << 1);
- if (0x00000000 != overflow) {
- descriptor.checksum += 1;
- }
- descriptor.checksum += buffer[bytes];
- }
- descriptor.checksum = PR_htonl(descriptor.checksum);
- for (loop = 0; loop < shared->messages; ++loop)
- {
- if (shared->debug > 1) {
- PR_fprintf(debug_out, "[%d]socket ... ", loop);
- }
- clientSock = PR_NewTCPSocket();
- if (clientSock)
- {
- /*
- * We need to slow down the rate of generating connect requests,
- * otherwise the listen backlog queue on the accept side may
- * become full and we will get connection refused or timeout
- * error.
- */
- PR_Sleep(shared->dally);
- if (shared->debug > 1)
- {
- char buf[128];
- PR_NetAddrToString(&shared->serverAddress, buf, sizeof(buf));
- PR_fprintf(debug_out, "connecting to %s ... ", buf);
- }
- rv = PR_Connect(
- clientSock, &shared->serverAddress, Timeout(shared));
- if (PR_SUCCESS == rv)
- {
- PRInt32 descriptor_length = (loop < (shared->messages - 1)) ?
- shared->message_length : 0;
- descriptor.length = PR_htonl(descriptor_length);
- if (shared->debug > 1)
- PR_fprintf(
- debug_out, "sending %d bytes ... ", descriptor_length);
- CauseTimeout(shared); /* might cause server to timeout */
- bytes = PR_Send(
- clientSock, &descriptor, sizeof(descriptor),
- flags, Timeout(shared));
- if (bytes != sizeof(descriptor))
- {
- shared->failed = PR_TRUE;
- if (shared->debug > 0) {
- PL_FPrintError(debug_out, "PR_Send failed");
- }
- }
- if (0 != descriptor_length)
- {
- CauseTimeout(shared);
- bytes = PR_Send(
- clientSock, buffer, descriptor_length,
- flags, Timeout(shared));
- if (bytes != descriptor_length)
- {
- shared->failed = PR_TRUE;
- if (shared->debug > 0) {
- PL_FPrintError(debug_out, "PR_Send failed");
- }
- }
- }
- if (shared->debug > 1) {
- PR_fprintf(debug_out, "closing ... ");
- }
- rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
- rv = PR_Close(clientSock);
- if (shared->debug > 1)
- {
- if (PR_SUCCESS == rv) {
- PR_fprintf(debug_out, "\n");
- }
- else {
- PL_FPrintError(debug_out, "shutdown failed");
- }
- }
- }
- else
- {
- if (shared->debug > 1) {
- PL_FPrintError(debug_out, "connect failed");
- }
- PR_Close(clientSock);
- if ((loop == 0) && (PR_GetError() == PR_CONNECT_REFUSED_ERROR))
- {
- if (MakeReceiver(shared) == PR_FAILURE) {
- break;
- }
- }
- else
- {
- if (shared->debug > 1) {
- PR_fprintf(debug_out, " exiting\n");
- }
- break;
- }
- }
- }
- else
- {
- shared->failed = PR_TRUE;
- if (shared->debug > 0) {
- PL_FPrintError(debug_out, "create socket");
- }
- break;
- }
- }
- PR_DELETE(buffer);
- } /* Connect */
- int Tmocon(int argc, char **argv)
- {
- /*
- * USAGE
- * -d turn on debugging output (default = off)
- * -v turn on verbose output (default = off)
- * -h <n> dns name of host serving the connection (default = self)
- * -i dally intermittantly to cause timeouts (default = off)
- * -m <n> number of messages to send (default = 100)
- * -s <n> size of each message (default = 100)
- * -t <n> number of threads sending (default = 1)
- * -G use global threads (default = local)
- * -T <n> timeout on I/O operations (seconds) (default = 10)
- * -D <n> dally between connect requests (seconds)(default = 0)
- * -R randomize the dally types around 'T' (default = no)
- */
- PRStatus rv;
- int exitStatus;
- PLOptStatus os;
- Shared *shared = NULL;
- PRThread **thread = NULL;
- PRIntn index, threads = DEFAULT_THREADS;
- PRThreadScope thread_scope = PR_LOCAL_THREAD;
- PRInt32 dally = DEFAULT_DALLY, timeout = DEFAULT_TIMEOUT;
- PLOptState *opt = PL_CreateOptState(argc, argv, "divGRh:m:s:t:T:D:");
- shared = PR_NEWZAP(Shared);
- shared->debug = 0;
- shared->failed = PR_FALSE;
- shared->random = PR_FALSE;
- shared->messages = DEFAULT_MESSAGES;
- shared->message_length = DEFAULT_MESSAGESIZE;
- PR_STDIO_INIT();
- memset(&shared->serverAddress, 0, sizeof(shared->serverAddress));
- rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &shared->serverAddress);
- PR_ASSERT(PR_SUCCESS == rv);
- while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
- {
- if (PL_OPT_BAD == os) {
- continue;
- }
- switch (opt->option)
- {
- case 'd':
- if (0 == shared->debug) {
- shared->debug = 1;
- }
- break;
- case 'v':
- if (0 == shared->debug) {
- shared->debug = 2;
- }
- break;
- case 'i':
- shared->intermittant = PR_TRUE;
- break;
- case 'R':
- shared->random = PR_TRUE;
- break;
- case 'G':
- thread_scope = PR_GLOBAL_THREAD;
- break;
- case 'h': /* the value for backlock */
- {
- PRIntn es = 0;
- PRHostEnt host;
- char buffer[1024];
- (void)PR_GetHostByName(
- opt->value, buffer, sizeof(buffer), &host);
- es = PR_EnumerateHostEnt(
- es, &host, BASE_PORT, &shared->serverAddress);
- PR_ASSERT(es > 0);
- }
- break;
- case 'm': /* number of messages to send */
- shared->messages = atoi(opt->value);
- break;
- case 't': /* number of threads sending */
- threads = atoi(opt->value);
- break;
- case 'D': /* dally time between transmissions */
- dally = atoi(opt->value);
- break;
- case 'T': /* timeout on I/O operations */
- timeout = atoi(opt->value);
- break;
- case 's': /* total size of each message */
- shared->message_length = atoi(opt->value);
- break;
- default:
- break;
- }
- }
- PL_DestroyOptState(opt);
- if (0 == timeout) {
- timeout = DEFAULT_TIMEOUT;
- }
- if (0 == threads) {
- threads = DEFAULT_THREADS;
- }
- if (0 == shared->messages) {
- shared->messages = DEFAULT_MESSAGES;
- }
- if (0 == shared->message_length) {
- shared->message_length = DEFAULT_MESSAGESIZE;
- }
- shared->dally = PR_SecondsToInterval(dally);
- shared->timeout = PR_SecondsToInterval(timeout);
- thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*));
- for (index = 0; index < threads; ++index)
- thread[index] = PR_CreateThread(
- PR_USER_THREAD, Connect, shared,
- PR_PRIORITY_NORMAL, thread_scope,
- PR_JOINABLE_THREAD, 0);
- for (index = 0; index < threads; ++index) {
- rv = PR_JoinThread(thread[index]);
- }
- PR_DELETE(thread);
- PR_fprintf(
- PR_GetSpecialFD(PR_StandardError), "%s\n",
- ((shared->failed) ? "FAILED" : "PASSED"));
- exitStatus = (shared->failed) ? 1 : 0;
- PR_DELETE(shared);
- return exitStatus;
- }
- int main(int argc, char **argv)
- {
- return (PR_VersionCheck(PR_VERSION)) ?
- PR_Initialize(Tmocon, argc, argv, 4) : -1;
- } /* main */
- /* tmocon.c */
|