tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

selct_nm.c (8285B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 /***********************************************************************
      7 **  1997 - Netscape Communications Corporation
      8 **
      9 ** Name: prselect_norm.c
     10 **
     11 ** Description: tests PR_Select with sockets - Normal operations.
     12 **
     13 ** Modification History:
     14 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
     15 **           The debug mode will print all of the printfs associated with this
     16 *test.
     17 **           The regress mode will be the default mode. Since the regress tool
     18 *limits
     19 **           the output to a one line status:PASS or FAIL,all of the printf
     20 *statements
     21 **           have been handled with an if (debug_mode) statement.
     22 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been
     23 *updated to
     24 **          recognize the return code from tha main program.
     25 ***********************************************************************/
     26 
     27 /***********************************************************************
     28 ** Includes
     29 ***********************************************************************/
     30 /* Used to get the command line option */
     31 #include "plgetopt.h"
     32 
     33 #include "prinit.h"
     34 #include "prio.h"
     35 #include "prlog.h"
     36 #include "prprf.h"
     37 #include "prerror.h"
     38 #include "prnetdb.h"
     39 
     40 #include "obsolete/probslet.h"
     41 
     42 #include <stdio.h>
     43 #include <string.h>
     44 #include <stdlib.h>
     45 
     46 PRIntn failed_already = 0;
     47 PRIntn debug_mode;
     48 
     49 static void clientThreadFunc(void* arg) {
     50  PRUintn port = (PRUintn)arg;
     51  PRFileDesc* sock;
     52  PRNetAddr addr;
     53  char buf[128];
     54  int i;
     55 
     56  addr.inet.family = PR_AF_INET;
     57  addr.inet.port = PR_htons((PRUint16)port);
     58  addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
     59  PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.port);
     60 
     61  for (i = 0; i < 5; i++) {
     62    sock = PR_NewTCPSocket();
     63    PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
     64    PR_Write(sock, buf, sizeof(buf));
     65    PR_Close(sock);
     66  }
     67 }
     68 
     69 int main(int argc, char** argv) {
     70  PRFileDesc *listenSock1, *listenSock2;
     71  PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds;
     72  PRIntn nfds;
     73  PRUint16 listenPort1, listenPort2;
     74  PRNetAddr addr;
     75  PR_fd_set readFdSet;
     76  char buf[128];
     77  PRThread* clientThread;
     78  PRInt32 retVal;
     79  PRIntn i, j;
     80 
     81  /* The command line argument: -d is used to determine if the test is being run
     82  in debug mode. The regress tool requires only one line output:PASS or FAIL.
     83  All of the printfs associated with this test has been handled with a if
     84  (debug_mode) test. Usage: test_name -d
     85  */
     86  PLOptStatus os;
     87  PLOptState* opt = PL_CreateOptState(argc, argv, "d:");
     88  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
     89    if (PL_OPT_BAD == os) {
     90      continue;
     91    }
     92    switch (opt->option) {
     93      case 'd': /* debug mode */
     94        debug_mode = 1;
     95        break;
     96      default:
     97        break;
     98    }
     99  }
    100  PL_DestroyOptState(opt);
    101 
    102  /* main test */
    103 
    104  PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    105 
    106  if (debug_mode) {
    107    printf("This program tests PR_Select with sockets.  \n");
    108    printf(" Normal operation are tested.\n\n");
    109  }
    110 
    111  /* Create two listening sockets */
    112  if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
    113    fprintf(stderr, "Can't create a new TCP socket\n");
    114    failed_already = 1;
    115    goto exit_now;
    116  }
    117  addr.inet.family = PR_AF_INET;
    118  addr.inet.ip = PR_htonl(PR_INADDR_ANY);
    119  addr.inet.port = PR_htons(0);
    120  if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
    121    fprintf(stderr, "Can't bind socket\n");
    122    failed_already = 1;
    123    goto exit_now;
    124  }
    125  if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
    126    fprintf(stderr, "PR_GetSockName failed\n");
    127    failed_already = 1;
    128    goto exit_now;
    129  }
    130  listenPort1 = PR_ntohs(addr.inet.port);
    131  if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
    132    fprintf(stderr, "Can't listen on a socket\n");
    133    failed_already = 1;
    134    goto exit_now;
    135  }
    136 
    137  if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
    138    fprintf(stderr, "Can't create a new TCP socket\n");
    139    failed_already = 1;
    140    goto exit_now;
    141  }
    142  addr.inet.family = PR_AF_INET;
    143  addr.inet.ip = PR_htonl(PR_INADDR_ANY);
    144  addr.inet.port = PR_htons(0);
    145  if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
    146    fprintf(stderr, "Can't bind socket\n");
    147    failed_already = 1;
    148    goto exit_now;
    149  }
    150  if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
    151    fprintf(stderr, "PR_GetSockName failed\n");
    152    failed_already = 1;
    153    goto exit_now;
    154  }
    155  listenPort2 = PR_ntohs(addr.inet.port);
    156  if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
    157    fprintf(stderr, "Can't listen on a socket\n");
    158    failed_already = 1;
    159    goto exit_now;
    160  }
    161  PR_snprintf(buf, sizeof(buf),
    162              "The server thread is listening on ports %hu and %hu\n\n",
    163              listenPort1, listenPort2);
    164  if (debug_mode) {
    165    printf("%s", buf);
    166  }
    167 
    168  clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc,
    169                                 (void*)listenPort1, PR_PRIORITY_NORMAL,
    170                                 PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
    171  if (clientThread == NULL) {
    172    fprintf(stderr, "can't create thread\n");
    173    failed_already = 1;
    174    goto exit_now;
    175  }
    176 
    177  clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc,
    178                                 (void*)listenPort2, PR_PRIORITY_NORMAL,
    179                                 PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
    180  if (clientThread == NULL) {
    181    fprintf(stderr, "can't create thread\n");
    182    failed_already = 1;
    183    goto exit_now;
    184  }
    185 
    186  if (debug_mode) {
    187    printf("Two client threads are created.  Each of them will\n");
    188    printf("send data to one of the two ports the server is listening on.\n");
    189    printf("The data they send is the port number.  Each of them send\n");
    190    printf("the data five times, so you should see ten lines below,\n");
    191    printf("interleaved in an arbitrary order.\n");
    192  }
    193  /* set up the fd array */
    194  fds = fds0;
    195  other_fds = fds1;
    196  fds[0] = listenSock1;
    197  fds[1] = listenSock2;
    198  nfds = 2;
    199  /* Set up the fd set */
    200  PR_FD_ZERO(&readFdSet);
    201  PR_FD_SET(listenSock1, &readFdSet);
    202  PR_FD_SET(listenSock2, &readFdSet);
    203 
    204  /* 20 events total */
    205  i = 0;
    206  while (i < 20) {
    207    PRFileDesc** tmp;
    208    int nextIndex;
    209    int nEvents = 0;
    210 
    211    retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
    212                       PR_INTERVAL_NO_TIMEOUT);
    213    PR_ASSERT(retVal != 0); /* no timeout */
    214    if (retVal == -1) {
    215      fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(),
    216              PR_GetOSError());
    217      failed_already = 1;
    218      goto exit_now;
    219    }
    220 
    221    nextIndex = 2;
    222    /* the two listening sockets */
    223    for (j = 0; j < 2; j++) {
    224      other_fds[j] = fds[j];
    225      if (PR_FD_ISSET(fds[j], &readFdSet)) {
    226        PRFileDesc* sock;
    227 
    228        nEvents++;
    229        sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT);
    230        if (sock == NULL) {
    231          fprintf(stderr, "PR_Accept() failed\n");
    232          failed_already = 1;
    233          goto exit_now;
    234        }
    235        other_fds[nextIndex] = sock;
    236        PR_FD_SET(sock, &readFdSet);
    237        nextIndex++;
    238      }
    239      PR_FD_SET(fds[j], &readFdSet);
    240    }
    241 
    242    for (j = 2; j < nfds; j++) {
    243      if (PR_FD_ISSET(fds[j], &readFdSet)) {
    244        PRInt32 nBytes;
    245 
    246        PR_FD_CLR(fds[j], &readFdSet);
    247        nEvents++;
    248        nBytes = PR_Read(fds[j], buf, sizeof(buf));
    249        if (nBytes == -1) {
    250          fprintf(stderr, "PR_Read() failed\n");
    251          failed_already = 1;
    252          goto exit_now;
    253        }
    254        /* Just to be safe */
    255        buf[127] = '\0';
    256        PR_Close(fds[j]);
    257        if (debug_mode) {
    258          printf("The server received \"%s\" from a client\n", buf);
    259        }
    260      } else {
    261        PR_FD_SET(fds[j], &readFdSet);
    262        other_fds[nextIndex] = fds[j];
    263        nextIndex++;
    264      }
    265    }
    266 
    267    PR_ASSERT(retVal == nEvents);
    268    /* swap */
    269    tmp = fds;
    270    fds = other_fds;
    271    other_fds = tmp;
    272    nfds = nextIndex;
    273    i += nEvents;
    274  }
    275 
    276  if (debug_mode) {
    277    printf("Test passed\n");
    278  }
    279 
    280  PR_Cleanup();
    281  goto exit_now;
    282 exit_now:
    283  if (failed_already) {
    284    return 1;
    285  } else {
    286    return 0;
    287  }
    288 }