Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
tmocon.c File Reference
#include "plgetopt.h"
#include "nspr.h"
#include "pprio.h"
#include "plerror.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Go to the source code of this file.

Classes

struct  Shared

Defines

#define BASE_PORT   9867
#define DEFAULT_DALLY   1
#define DEFAULT_THREADS   1
#define DEFAULT_TIMEOUT   10
#define DEFAULT_MESSAGES   100
#define DEFAULT_MESSAGESIZE   100

Typedefs

typedef struct Shared Shared

Functions

static PRIntervalTime Timeout (const Shared *shared)
static void CauseTimeout (const Shared *shared)
static PRStatus MakeReceiver (Shared *shared)
static void Connect (void *arg)
int Tmocon (int argc, char **argv)
int main (int argc, char **argv)
 The Xalan testcases app.

Variables

static PRFileDescdebug_out = NULL

Define Documentation

#define BASE_PORT   9867

Definition at line 81 of file tmocon.c.

Definition at line 83 of file tmocon.c.

Definition at line 86 of file tmocon.c.

Definition at line 87 of file tmocon.c.

Definition at line 84 of file tmocon.c.

Definition at line 85 of file tmocon.c.


Typedef Documentation

typedef struct Shared Shared

Function Documentation

static void CauseTimeout ( const Shared shared) [static]

Definition at line 116 of file tmocon.c.

{
    if (shared->intermittant) PR_Sleep(Timeout(shared));
}  /* CauseTimeout */

Here is the call graph for this function:

Here is the caller graph for this function:

static void Connect ( void arg) [static]

Definition at line 161 of file tmocon.c.

{
    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 */

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

The Xalan testcases app.

Definition at line 396 of file tmocon.c.

{
    return (PR_VersionCheck(PR_VERSION)) ?
        PR_Initialize(Tmocon, argc, argv, 4) : -1;
}  /* main */

Here is the call graph for this function:

static PRStatus MakeReceiver ( Shared shared) [static]

Definition at line 121 of file tmocon.c.

{
    PRStatus rv = PR_FAILURE;
    if (PR_IsNetAddrType(&shared->serverAddress, PR_IpAddrLoopback))
    {
        char *argv[3];
        char path[1024 + sizeof("/tmoacc")];
        (void)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 */

Here is the call graph for this function:

Here is the caller graph for this function:

static PRIntervalTime Timeout ( const Shared shared) [static]

Definition at line 104 of file tmocon.c.

{
    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 */

Here is the call graph for this function:

Here is the caller graph for this function:

int Tmocon ( int  argc,
char **  argv 
)

Definition at line 275 of file tmocon.c.

{
    /*
     * 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;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

PRFileDesc* debug_out = NULL [static]

Definition at line 89 of file tmocon.c.