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


Quelle  nbconn.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/. */


/*
 * A test for nonblocking connect.  Functions tested include PR_Connect,
 * PR_Poll, and PR_GetConnectStatus.
 *
 * The test should be invoked with a host name, for example:
 *     nbconn www.netscape.com
 * It will do a nonblocking connect to port 80 (HTTP) on that host,
 * and when connected, issue the "GET /" HTTP command.
 *
 * You should run this test in three ways:
 * 1. To a known web site, such as www.netscape.com.  The HTML of the
 *    top-level page at the web site should be printed.
 * 2. To a machine not running a web server at port 80.  This test should
 *    fail.  Ideally the error code should be PR_CONNECT_REFUSED_ERROR.
 *    But it is possible to return PR_UNKNOWN_ERROR on certain platforms.
 * 3. To an unreachable machine, for example, a machine that is off line.
 *    The test should fail after the connect times out.  Ideally the
 *    error code should be PR_IO_TIMEOUT_ERROR, but it is possible to
 *    return PR_UNKNOWN_ERROR on certain platforms.
 */


#include "nspr.h"
#include "plgetopt.h"
#include <stdio.h>
#include <string.h>

#define SERVER_MAX_BIND_COUNT 100
#define DATA_BUF_SIZE 256
#define TCP_SERVER_PORT 10000
#define TCP_UNUSED_PORT 211

typedef struct Server_Param {
  PRFileDesc* sp_fd; /* server port */
} Server_Param;
static void PR_CALLBACK TCP_Server(void* arg);

int _debug_on;
#define DPRINTF(arg) \
  if (_debug_on) printf arg

static PRIntn connection_success_test();
static PRIntn connection_failure_test();

int main(int argc, char** argv) {
  PRHostEnt he;
  char buf[1024];
  PRNetAddr addr;
  PRPollDesc pd;
  PRStatus rv;
  PRSocketOptionData optData;
  const char* hostname = NULL;
  PRIntn default_case, n, bytes_read, bytes_sent;
  PRInt32 failed_already = 0;

  /*
   * -d           debug mode
   */


  PLOptStatus os;
  PLOptState* opt = PL_CreateOptState(argc, argv, "d");
  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    if (PL_OPT_BAD == os) {
      continue;
    }
    switch (opt->option) {
      case 0: /* debug mode */
        hostname = opt->value;
        break;
      case 'd'/* debug mode */
        _debug_on = 1;
        break;
      default:
        break;
    }
  }
  PL_DestroyOptState(opt);

  PR_STDIO_INIT();
  if (hostname) {
    default_case = 0;
  } else {
    default_case = 1;
  }

  if (default_case) {
    /*
     * In the default case the following tests are executed:
     *  1. successful connection: a server thread accepts a connection
     *     from the main thread
     *  2. unsuccessful connection: the main thread tries to connect to a
     *     nonexistent port and expects to get an error
     */

    rv = connection_success_test();
    if (rv == 0) {
      rv = connection_failure_test();
    }
    return rv;
  } else {
    PRFileDesc* sock;

    if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) {
      printf("Unknown host: %s\n", argv[1]);
      exit(1);
    } else {
      printf("host: %s\n", buf);
    }
    PR_EnumerateHostEnt(0, &he, 80, &addr);

    sock = PR_NewTCPSocket();
    optData.option = PR_SockOpt_Nonblocking;
    optData.value.non_blocking = PR_TRUE;
    PR_SetSocketOption(sock, &optData);
    rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
    if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
      printf("Connect in progress\n");
    }

    pd.fd = sock;
    pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
    n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
    if (n == -1) {
      printf("PR_Poll failed\n");
      exit(1);
    }
    printf("PR_Poll returns %d\n", n);
    if (pd.out_flags & PR_POLL_READ) {
      printf("PR_POLL_READ\n");
    }
    if (pd.out_flags & PR_POLL_WRITE) {
      printf("PR_POLL_WRITE\n");
    }
    if (pd.out_flags & PR_POLL_EXCEPT) {
      printf("PR_POLL_EXCEPT\n");
    }
    if (pd.out_flags & PR_POLL_ERR) {
      printf("PR_POLL_ERR\n");
    }
    if (pd.out_flags & PR_POLL_NVAL) {
      printf("PR_POLL_NVAL\n");
    }

    if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
      printf("PR_GetConnectStatus: connect succeeded\n");
      PR_Write(sock, "GET /\r\n\r\n", 9);
      PR_Shutdown(sock, PR_SHUTDOWN_SEND);
      pd.in_flags = PR_POLL_READ;
      while (1) {
        n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
        printf("poll returns %d\n", n);
        n = PR_Read(sock, buf, sizeof(buf));
        printf("read returns %d\n", n);
        if (n <= 0) {
          break;
        }
        PR_Write(PR_STDOUT, buf, n);
      }
    } else {
      if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
        printf("PR_GetConnectStatus: connect still in progress\n");
        exit(1);
      }
      printf("PR_GetConnectStatus: connect failed: (%ld, %ld)\n", PR_GetError(),
             PR_GetOSError());
    }
    PR_Close(sock);
    printf("PASS\n");
    return 0;
  }
}

/*
 * TCP Server
 *    Server Thread
 *    Accept a connection from the client and write some data
 */

static void PR_CALLBACK TCP_Server(void* arg) {
  Server_Param* sp = (Server_Param*)arg;
  PRFileDesc *sockfd, *newsockfd;
  char data_buf[DATA_BUF_SIZE];
  PRIntn rv, bytes_read;

  sockfd = sp->sp_fd;
  if ((newsockfd = PR_Accept(sockfd, NULL, PR_INTERVAL_NO_TIMEOUT)) == NULL) {
    fprintf(stderr, "ERROR - PR_Accept failed: (%d,%d)\n", PR_GetError(),
            PR_GetOSError());
    return;
  }
  bytes_read = 0;
  while (bytes_read != DATA_BUF_SIZE) {
    rv = PR_Read(newsockfd, data_buf + bytes_read, DATA_BUF_SIZE - bytes_read);
    if (rv < 0) {
      fprintf(stderr, "Error - PR_Read failed: (%d, %d)\n", PR_GetError(),
              PR_GetOSError());
      PR_Close(newsockfd);
      return;
    }
    PR_ASSERT(rv != 0);
    bytes_read += rv;
  }
  DPRINTF(("Bytes read from client - %d\n", bytes_read));
  rv = PR_Write(newsockfd, data_buf, DATA_BUF_SIZE);
  if (rv < 0) {
    fprintf(stderr, "Error - PR_Write failed: (%d, %d)\n", PR_GetError(),
            PR_GetOSError());
    PR_Close(newsockfd);
    return;
  }
  PR_ASSERT(rv == DATA_BUF_SIZE);
  DPRINTF(("Bytes written to client - %d\n", rv));
  PR_Close(newsockfd);
}

/*
 * test for successful connection using a non-blocking socket
 */

static PRIntn connection_success_test() {
  PRFileDesc *sockfd = NULL, *conn_fd = NULL;
  PRNetAddr netaddr;
  PRInt32 i, rv;
  PRPollDesc pd;
  PRSocketOptionData optData;
  PRThread* thr = NULL;
  Server_Param sp;
  char send_buf[DATA_BUF_SIZE], recv_buf[DATA_BUF_SIZE];
  PRIntn default_case, n, bytes_read, bytes_sent;
  PRIntn failed_already = 0;

  /*
   * Create a tcp socket
   */

  if ((sockfd = PR_NewTCPSocket()) == NULL) {
    fprintf(stderr, "Error - PR_NewTCPSocket failed\n");
    failed_already = 1;
    goto def_exit;
  }
  memset(&netaddr, 0, sizeof(netaddr));
  netaddr.inet.family = PR_AF_INET;
  netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
  netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
  /*
   * try a few times to bind server's address, if addresses are in
   * use
   */

  i = 0;
  while (PR_Bind(sockfd, &netaddr) < 0) {
    if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
      netaddr.inet.port += 2;
      if (i++ < SERVER_MAX_BIND_COUNT) {
        continue;
      }
    }
    fprintf(stderr, "ERROR - PR_Bind failed: (%d,%d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }

  if (PR_Listen(sockfd, 32) < 0) {
    fprintf(stderr, "ERROR - PR_Listen failed: (%d,%d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }

  if (PR_GetSockName(sockfd, &netaddr) < 0) {
    fprintf(stderr, "ERROR - PR_GetSockName failed: (%d,%d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }
  if ((conn_fd = PR_NewTCPSocket()) == NULL) {
    fprintf(stderr, "Error - PR_NewTCPSocket failed\n");
    failed_already = 1;
    goto def_exit;
  }
  optData.option = PR_SockOpt_Nonblocking;
  optData.value.non_blocking = PR_TRUE;
  PR_SetSocketOption(conn_fd, &optData);
  rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
  if (rv == PR_FAILURE) {
    if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
      DPRINTF(("Connect in progress\n"));
    } else {
      fprintf(stderr, "Error - PR_Connect failed: (%d, %d)\n", PR_GetError(),
              PR_GetOSError());
      failed_already = 1;
      goto def_exit;
    }
  }
  /*
   * Now create a thread to accept a connection
   */

  sp.sp_fd = sockfd;
  thr = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void*)&sp,
                        PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD,
                        0);
  if (thr == NULL) {
    fprintf(stderr, "Error - PR_CreateThread failed: (%d,%d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }
  DPRINTF(("Created TCP_Server thread [0x%x]\n", thr));
  pd.fd = conn_fd;
  pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
  n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
  if (n == -1) {
    fprintf(stderr, "Error - PR_Poll failed: (%d, %d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }
  if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
    PRInt32 rv;

    DPRINTF(("Connection successful\n"));

    /*
     * Write some data, read it back and check data integrity to
     * make sure the connection is good
     */

    pd.in_flags = PR_POLL_WRITE;
    bytes_sent = 0;
    memset(send_buf, 'a', DATA_BUF_SIZE);
    while (bytes_sent != DATA_BUF_SIZE) {
      rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
      if (rv < 0) {
        fprintf(stderr, "Error - PR_Poll failed: (%d, %d)\n", PR_GetError(),
                PR_GetOSError());
        failed_already = 1;
        goto def_exit;
      }
      PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_WRITE));
      rv = PR_Write(conn_fd, send_buf + bytes_sent, DATA_BUF_SIZE - bytes_sent);
      if (rv < 0) {
        fprintf(stderr, "Error - PR_Write failed: (%d, %d)\n", PR_GetError(),
                PR_GetOSError());
        failed_already = 1;
        goto def_exit;
      }
      PR_ASSERT(rv > 0);
      bytes_sent += rv;
    }
    DPRINTF(("Bytes written to server - %d\n", bytes_sent));
    PR_Shutdown(conn_fd, PR_SHUTDOWN_SEND);
    pd.in_flags = PR_POLL_READ;
    bytes_read = 0;
    memset(recv_buf, 0, DATA_BUF_SIZE);
    while (bytes_read != DATA_BUF_SIZE) {
      rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
      if (rv < 0) {
        fprintf(stderr, "Error - PR_Poll failed: (%d, %d)\n", PR_GetError(),
                PR_GetOSError());
        failed_already = 1;
        goto def_exit;
      }
      PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_READ));
      rv = PR_Read(conn_fd, recv_buf + bytes_read, DATA_BUF_SIZE - bytes_read);
      if (rv < 0) {
        fprintf(stderr, "Error - PR_Read failed: (%d, %d)\n", PR_GetError(),
                PR_GetOSError());
        failed_already = 1;
        goto def_exit;
      }
      PR_ASSERT(rv != 0);
      bytes_read += rv;
    }
    DPRINTF(("Bytes read from server - %d\n", bytes_read));
    /*
     * verify the data read
     */

    if (memcmp(send_buf, recv_buf, DATA_BUF_SIZE) != 0) {
      fprintf(stderr, "ERROR - data corruption\n");
      failed_already = 1;
      goto def_exit;
    }
    DPRINTF(("Data integrity verified\n"));
  } else {
    fprintf(stderr, "PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
            PR_GetError(), PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }
def_exit:
  if (thr) {
    PR_JoinThread(thr);
    thr = NULL;
  }
  if (sockfd) {
    PR_Close(sockfd);
    sockfd = NULL;
  }
  if (conn_fd) {
    PR_Close(conn_fd);
    conn_fd = NULL;
  }
  if (failed_already) {
    return 1;
  } else {
    return 0;
  }
}

/*
 * test for connection to a nonexistent port using a non-blocking socket
 */

static PRIntn connection_failure_test() {
  PRFileDesc *sockfd = NULL, *conn_fd = NULL;
  PRNetAddr netaddr;
  PRInt32 i, rv;
  PRPollDesc pd;
  PRSocketOptionData optData;
  PRIntn n, failed_already = 0;

  /*
   * Create a tcp socket
   */

  if ((sockfd = PR_NewTCPSocket()) == NULL) {
    fprintf(stderr, "Error - PR_NewTCPSocket failed\n");
    failed_already = 1;
    goto def_exit;
  }
  memset(&netaddr, 0, sizeof(netaddr));
  netaddr.inet.family = PR_AF_INET;
  netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
  netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
  /*
   * try a few times to bind server's address, if addresses are in
   * use
   */

  i = 0;
  while (PR_Bind(sockfd, &netaddr) < 0) {
    if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
      netaddr.inet.port += 2;
      if (i++ < SERVER_MAX_BIND_COUNT) {
        continue;
      }
    }
    fprintf(stderr, "ERROR - PR_Bind failed: (%d,%d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }

  if (PR_GetSockName(sockfd, &netaddr) < 0) {
    fprintf(stderr, "ERROR - PR_GetSockName failed: (%d,%d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }
#ifdef AIX
  /*
   * On AIX, set to unused/reserved port
   */

  netaddr.inet.port = PR_htons(TCP_UNUSED_PORT);
#endif
  if ((conn_fd = PR_NewTCPSocket()) == NULL) {
    fprintf(stderr, "Error - PR_NewTCPSocket failed\n");
    failed_already = 1;
    goto def_exit;
  }
  optData.option = PR_SockOpt_Nonblocking;
  optData.value.non_blocking = PR_TRUE;
  PR_SetSocketOption(conn_fd, &optData);
  rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
  if (rv == PR_FAILURE) {
    DPRINTF(("PR_Connect to a non-listen port failed: (%d, %d)\n",
             PR_GetError(), PR_GetOSError()));
  } else {
    PR_ASSERT(rv == PR_SUCCESS);
    fprintf(stderr, "Error - PR_Connect succeeded, expected to fail\n");
    failed_already = 1;
    goto def_exit;
  }
  pd.fd = conn_fd;
  pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
  n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
  if (n == -1) {
    fprintf(stderr, "Error - PR_Poll failed: (%d, %d)\n", PR_GetError(),
            PR_GetOSError());
    failed_already = 1;
    goto def_exit;
  }
  if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
    PRInt32 rv;
    fprintf(stderr, "PR_GetConnectStatus succeeded, expected to fail\n");
    failed_already = 1;
    goto def_exit;
  }
  rv = PR_GetError();
  DPRINTF(("Connection failed, successfully with PR_Error %d\n", rv));
def_exit:
  if (sockfd) {
    PR_Close(sockfd);
    sockfd = NULL;
  }
  if (conn_fd) {
    PR_Close(conn_fd);
    conn_fd = NULL;
  }
  if (failed_already) {
    return 1;
  } else {
    return 0;
  }
}

Messung V0.5
C=89 H=93 G=90

¤ Dauer der Verarbeitung: 0.1 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