Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  tmocon.c   Sprache: C

 
/* -*- 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)
#  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 */

Messung V0.5
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge