tor-browser

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

test_socket.c (20171B)


      1 /*
      2 * test_socket.c
      3 *
      4 * Test Socket Type
      5 *
      6 * Copyright 2004-2005 Sun Microsystems, Inc.  All rights reserved.
      7 *
      8 * Redistribution and use in source and binary forms, with or without
      9 * modification, are permitted provided that the following conditions are met:
     10 *
     11 *   1. Redistribution of source code must retain the above copyright notice,
     12 *      this list of conditions and the following disclaimer.
     13 *
     14 *   2. Redistribution in binary form must reproduce the above copyright
     15 *      notice, this list of conditions and the following disclaimer in the
     16 *      documentation and/or other materials provided with the distribution.
     17 *
     18 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
     19 * be used to endorse or promote products derived from this software without
     20 * specific prior written permission.
     21 *
     22 * This software is provided "AS IS," without a warranty of any kind. ALL
     23 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
     24 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
     25 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
     26 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
     27 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
     28 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
     29 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
     30 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
     31 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
     32 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
     33 *
     34 * You acknowledge that this software is not designed or intended for use in
     35 * the design, construction, operation or maintenance of any nuclear facility.
     36 */
     37 
     38 #include "testutil.h"
     39 #include "testutil_nss.h"
     40 #include "pkix_pl_common.h"
     41 
     42 #define LDAP_PORT 389
     43 
     44 static void *plContext = NULL;
     45 
     46 typedef enum {
     47    SERVER_LISTENING,
     48    SERVER_RECV1,
     49    SERVER_POLL1,
     50    SERVER_SEND2,
     51    SERVER_POLL2,
     52    SERVER_RECV3,
     53    SERVER_POLL3,
     54    SERVER_SEND4,
     55    SERVER_POLL4,
     56    SERVER_DONE,
     57    SERVER_FAILED
     58 } SERVER_STATE;
     59 
     60 typedef enum {
     61    CLIENT_WAITFORCONNECT,
     62    CLIENT_SEND1,
     63    CLIENT_POLL1,
     64    CLIENT_RECV2,
     65    CLIENT_POLL2,
     66    CLIENT_SEND3,
     67    CLIENT_POLL3,
     68    CLIENT_RECV4,
     69    CLIENT_POLL4,
     70    CLIENT_DONE,
     71    CLIENT_FAILED
     72 } CLIENT_STATE;
     73 
     74 SERVER_STATE serverState;
     75 CLIENT_STATE clientState;
     76 PKIX_PL_Socket *sSock = NULL;
     77 PKIX_PL_Socket *cSock = NULL;
     78 PKIX_PL_Socket *rendezvousSock = NULL;
     79 PKIX_PL_Socket_Callback *sCallbackList;
     80 PKIX_PL_Socket_Callback *cCallbackList;
     81 PKIX_PL_Socket_Callback *rvCallbackList;
     82 PRNetAddr serverNetAddr;
     83 PRNetAddr clientNetAddr;
     84 PRIntn backlog = 0;
     85 PRIntervalTime timeout = 0;
     86 char *sendBuf1 = "Hello, world!";
     87 char *sendBuf2 = "Ack";
     88 char *sendBuf3 = "What do you mean, \"Ack\"?";
     89 char *sendBuf4 = "What do you mean, \"What do you mean, \'Ack\'?\"?";
     90 char rcvBuf1[100];
     91 char rcvBuf2[100];
     92 
     93 static void
     94 printUsage(char *testname)
     95 {
     96    char *fmt = "USAGE: %s [-arenas] server:port\n";
     97    printf(fmt, testname);
     98 }
     99 
    100 /* Functional tests for Socket public functions */
    101 static void
    102 do_other_work(void)
    103 { /* while waiting for nonblocking I/O to complete */
    104    (void)PR_Sleep(2 * 60);
    105 }
    106 
    107 static PKIX_Boolean
    108 server()
    109 {
    110    PKIX_Int32 bytesRead = 0;
    111    PKIX_Int32 bytesWritten = 0;
    112    PKIX_Boolean keepGoing = PKIX_FALSE;
    113 
    114    PKIX_TEST_STD_VARS();
    115 
    116    switch (serverState) {
    117        case SERVER_LISTENING:
    118            subTest("SERVER_LISTENING");
    119            PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->acceptCallback(sSock, &rendezvousSock, plContext));
    120            if (rendezvousSock) {
    121                PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(rendezvousSock, &rvCallbackList, plContext));
    122 
    123                serverState = SERVER_RECV1;
    124            }
    125            break;
    126        case SERVER_RECV1:
    127            subTest("SERVER_RECV1");
    128            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock,
    129                                                                   rcvBuf1,
    130                                                                   sizeof(rcvBuf1),
    131                                                                   &bytesRead,
    132                                                                   plContext));
    133 
    134            if (bytesRead > 0) {
    135                /* confirm that rcvBuf1 = sendBuf1 */
    136                if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) ||
    137                    (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) {
    138                    testError("Receive buffer mismatch\n");
    139                }
    140 
    141                serverState = SERVER_SEND2;
    142                keepGoing = PKIX_TRUE;
    143            } else {
    144                serverState = SERVER_POLL1;
    145            }
    146            break;
    147        case SERVER_POLL1:
    148            subTest("SERVER_POLL1");
    149            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext));
    150 
    151            if (bytesRead > 0) {
    152                /* confirm that rcvBuf1 = sendBuf1 */
    153                if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) ||
    154                    (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) {
    155                    testError("Receive buffer mismatch\n");
    156                }
    157 
    158                serverState = SERVER_SEND2;
    159                keepGoing = PKIX_TRUE;
    160            }
    161            break;
    162        case SERVER_SEND2:
    163            subTest("SERVER_SEND2");
    164            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock,
    165                                                                   sendBuf2,
    166                                                                   strlen(sendBuf2) +
    167                                                                       1,
    168                                                                   &bytesWritten,
    169                                                                   plContext));
    170            if (bytesWritten > 0) {
    171                serverState = SERVER_RECV3;
    172            } else {
    173                serverState = SERVER_POLL2;
    174            }
    175            break;
    176        case SERVER_POLL2:
    177            subTest("SERVER_POLL2");
    178            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext));
    179            if (bytesWritten > 0) {
    180                serverState = SERVER_RECV3;
    181            }
    182            break;
    183        case SERVER_RECV3:
    184            subTest("SERVER_RECV3");
    185            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock,
    186                                                                   rcvBuf1,
    187                                                                   sizeof(rcvBuf1),
    188                                                                   &bytesRead,
    189                                                                   plContext));
    190 
    191            if (bytesRead > 0) {
    192                serverState = SERVER_SEND4;
    193                keepGoing = PKIX_TRUE;
    194            } else {
    195                serverState = SERVER_POLL3;
    196            }
    197            break;
    198        case SERVER_POLL3:
    199            subTest("SERVER_POLL3");
    200            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext));
    201            if (bytesRead > 0) {
    202                serverState = SERVER_SEND4;
    203                keepGoing = PKIX_TRUE;
    204            }
    205            break;
    206        case SERVER_SEND4:
    207            subTest("SERVER_SEND4");
    208            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock,
    209                                                                   sendBuf4,
    210                                                                   strlen(sendBuf4) +
    211                                                                       1,
    212                                                                   &bytesWritten,
    213                                                                   plContext));
    214 
    215            if (bytesWritten > 0) {
    216                PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext));
    217                PKIX_TEST_DECREF_BC(sSock);
    218                PKIX_TEST_DECREF_BC(rendezvousSock);
    219                serverState = SERVER_DONE;
    220            } else {
    221                serverState = SERVER_POLL4;
    222            }
    223            break;
    224        case SERVER_POLL4:
    225            subTest("SERVER_POLL4");
    226            PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext));
    227            if (bytesWritten > 0) {
    228                PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext));
    229                PKIX_TEST_DECREF_BC(sSock);
    230                PKIX_TEST_DECREF_BC(rendezvousSock);
    231                serverState = SERVER_DONE;
    232            }
    233            break;
    234        case SERVER_DONE:
    235        default:
    236            subTest("SERVER_DONE");
    237            break;
    238    }
    239 
    240 cleanup:
    241 
    242    PKIX_TEST_RETURN();
    243 
    244    return (keepGoing);
    245 }
    246 
    247 static PKIX_Boolean
    248 client()
    249 {
    250    PKIX_Boolean keepGoing = PKIX_FALSE;
    251    PKIX_Int32 bytesRead = 0;
    252    PKIX_Int32 bytesWritten = 0;
    253    PRErrorCode cStat = 0;
    254 
    255    /* At 2 seconds each cycle, this should suffice! */
    256    PKIX_UInt32 giveUpCount = 10;
    257 
    258    PKIX_TEST_STD_VARS();
    259 
    260    switch (clientState) {
    261        case CLIENT_WAITFORCONNECT:
    262            subTest("CLIENT_WAITFORCONNECT");
    263            clientState = CLIENT_FAILED;
    264            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->connectcontinueCallback(cSock, &cStat, plContext));
    265            if (cStat == 0) {
    266                clientState = CLIENT_SEND1;
    267                keepGoing = PKIX_TRUE;
    268            } else {
    269                clientState = CLIENT_WAITFORCONNECT;
    270                if (--giveUpCount == 0) {
    271                    testError("Client unable to connect");
    272                }
    273            }
    274            break;
    275        case CLIENT_SEND1:
    276            subTest("CLIENT_SEND1");
    277            clientState = CLIENT_FAILED;
    278            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock,
    279                                                                  sendBuf1,
    280                                                                  strlen(sendBuf1) +
    281                                                                      1,
    282                                                                  &bytesWritten,
    283                                                                  plContext));
    284            if (bytesWritten > 0) {
    285                clientState = CLIENT_RECV2;
    286            } else {
    287                clientState = CLIENT_POLL1;
    288            }
    289            break;
    290        case CLIENT_POLL1:
    291            subTest("CLIENT_POLL1");
    292            clientState = CLIENT_FAILED;
    293            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext));
    294            if (bytesWritten > 0) {
    295                clientState = CLIENT_RECV2;
    296            } else {
    297                clientState = CLIENT_POLL1;
    298            }
    299            break;
    300        case CLIENT_RECV2:
    301            subTest("CLIENT_RECV2");
    302            clientState = CLIENT_FAILED;
    303            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock,
    304                                                                  rcvBuf2,
    305                                                                  sizeof(rcvBuf2),
    306                                                                  &bytesRead,
    307                                                                  plContext));
    308 
    309            if (bytesRead > 0) {
    310                /* confirm that rcvBuf2 = sendBuf2 */
    311                if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) ||
    312                    (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) {
    313                    testError("Receive buffer mismatch\n");
    314                }
    315                clientState = CLIENT_SEND3;
    316                keepGoing = PKIX_TRUE;
    317            } else {
    318                clientState = CLIENT_POLL2;
    319            }
    320            break;
    321        case CLIENT_POLL2:
    322            subTest("CLIENT_POLL2");
    323            clientState = CLIENT_FAILED;
    324            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext));
    325            if (bytesRead > 0) {
    326                /* confirm that rcvBuf2 = sendBuf2 */
    327                if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) ||
    328                    (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) {
    329                    testError("Receive buffer mismatch\n");
    330                }
    331                clientState = CLIENT_SEND3;
    332            } else {
    333                clientState = CLIENT_POLL2;
    334            }
    335            break;
    336        case CLIENT_SEND3:
    337            subTest("CLIENT_SEND3");
    338            clientState = CLIENT_FAILED;
    339            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock,
    340                                                                  sendBuf3,
    341                                                                  strlen(sendBuf3) +
    342                                                                      1,
    343                                                                  &bytesWritten,
    344                                                                  plContext));
    345 
    346            if (bytesWritten > 0) {
    347                clientState = CLIENT_RECV4;
    348            } else {
    349                clientState = CLIENT_POLL3;
    350            }
    351            break;
    352        case CLIENT_POLL3:
    353            subTest("CLIENT_POLL3");
    354            clientState = CLIENT_FAILED;
    355            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext));
    356            if (bytesWritten > 0) {
    357                clientState = CLIENT_RECV4;
    358            } else {
    359                clientState = CLIENT_POLL3;
    360            }
    361            break;
    362        case CLIENT_RECV4:
    363            subTest("CLIENT_RECV4");
    364            clientState = CLIENT_FAILED;
    365            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock,
    366                                                                  rcvBuf2,
    367                                                                  sizeof(rcvBuf2),
    368                                                                  &bytesRead,
    369                                                                  plContext));
    370 
    371            if (bytesRead > 0) {
    372                PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext));
    373                PKIX_TEST_DECREF_BC(cSock);
    374                clientState = CLIENT_DONE;
    375            } else {
    376                clientState = CLIENT_POLL4;
    377            }
    378            break;
    379        case CLIENT_POLL4:
    380            subTest("CLIENT_POLL4");
    381            clientState = CLIENT_FAILED;
    382            PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext));
    383            if (bytesRead > 0) {
    384                PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext));
    385                PKIX_TEST_DECREF_BC(cSock);
    386                clientState = CLIENT_DONE;
    387            } else {
    388                clientState = CLIENT_POLL4;
    389            }
    390            break;
    391        case CLIENT_DONE:
    392        default:
    393            subTest("CLIENT_DONE");
    394            break;
    395    }
    396 
    397 cleanup:
    398 
    399    PKIX_TEST_RETURN();
    400 
    401    return (keepGoing);
    402 }
    403 
    404 static void
    405 dispatcher()
    406 {
    407    PKIX_Boolean keepGoing = PKIX_FALSE;
    408 
    409    PKIX_TEST_STD_VARS();
    410 
    411    do {
    412        if (serverState < SERVER_DONE) {
    413            do {
    414                keepGoing = server();
    415            } while (keepGoing == PKIX_TRUE);
    416        }
    417        if (clientState < CLIENT_DONE) {
    418            do {
    419                keepGoing = client();
    420            } while (keepGoing == PKIX_TRUE);
    421        }
    422        do_other_work();
    423 
    424    } while ((serverState < SERVER_DONE) || (clientState < CLIENT_DONE));
    425 
    426    PKIX_TEST_RETURN();
    427 }
    428 
    429 int
    430 test_socket(int argc, char *argv[])
    431 {
    432 
    433    int j = 0;
    434    PKIX_UInt32 actualMinorVersion;
    435    char buf[PR_NETDB_BUF_SIZE];
    436    char *serverName = NULL;
    437    char *sepPtr = NULL;
    438    PRHostEnt hostent;
    439    PRUint16 portNum = 0;
    440    PRStatus prstatus = PR_FAILURE;
    441    PRErrorCode cStat = 0;
    442    void *ipaddr = NULL;
    443    PKIX_Error *bindError = NULL;
    444    PRIntn hostenum;
    445 
    446    PKIX_TEST_STD_VARS();
    447 
    448    startTests("Socket");
    449 
    450    PKIX_TEST_EXPECT_NO_ERROR(
    451        PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
    452 
    453    if (argc != (j + 2)) {
    454        printUsage(argv[0]);
    455        pkixTestErrorMsg = "Missing command line argument.";
    456        goto cleanup;
    457    }
    458 
    459    serverName = argv[j + 1];
    460 
    461    subTest("Using pkix_pl_Socket_CreateByName");
    462 
    463    PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_TRUE, timeout, serverName, &cStat, &sSock, plContext));
    464 
    465    PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext));
    466 
    467    PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext));
    468 
    469    serverState = SERVER_LISTENING;
    470 
    471    PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_FALSE, timeout, serverName, &cStat, &cSock, plContext));
    472 
    473    PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext));
    474 
    475    if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) {
    476        clientState = CLIENT_WAITFORCONNECT;
    477    } else {
    478        clientState = CLIENT_SEND1;
    479    }
    480 
    481    dispatcher();
    482 
    483    subTest("Using pkix_pl_Socket_Create");
    484 
    485    sepPtr = strchr(serverName, ':');
    486    /* First strip off the portnum, if present, from the end of the name */
    487    if (sepPtr) {
    488        *sepPtr++ = '\0';
    489        portNum = (PRUint16)atoi(sepPtr);
    490    } else {
    491        portNum = (PRUint16)LDAP_PORT;
    492    }
    493    /*
    494     * The hostname may be a fully-qualified name. Just
    495     * use the leftmost component in our lookup.
    496     */
    497    sepPtr = strchr(serverName, '.');
    498    if (sepPtr) {
    499        *sepPtr++ = '\0';
    500    }
    501    prstatus = PR_GetHostByName(serverName, buf, sizeof(buf), &hostent);
    502 
    503    if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
    504        printUsage(argv[0]);
    505        pkixTestErrorMsg =
    506            "PR_GetHostByName rejects command line argument.";
    507        goto cleanup;
    508    }
    509 
    510    serverNetAddr.inet.family = PR_AF_INET;
    511    serverNetAddr.inet.port = PR_htons(portNum);
    512    serverNetAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
    513 
    514    hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &clientNetAddr);
    515    if (hostenum == -1) {
    516        pkixTestErrorMsg =
    517            "PR_EnumerateHostEnt failed.";
    518        goto cleanup;
    519    }
    520 
    521    backlog = 5;
    522 
    523    /* timeout = PR_INTERVAL_NO_TIMEOUT; */
    524    /* timeout = 0; nonblocking */
    525    timeout = 0;
    526 
    527    bindError = pkix_pl_Socket_Create(PKIX_TRUE, timeout, &serverNetAddr, &cStat, &sSock, plContext);
    528 
    529    /* If PR_Bind can't handle INADDR_ANY, try it with the real name */
    530    if (bindError) {
    531        PKIX_TEST_DECREF_BC(bindError);
    532        serverNetAddr.inet.ip = PR_htonl(*(PRUint32 *)ipaddr);
    533 
    534        PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_TRUE,
    535                                                        timeout,
    536                                                        &serverNetAddr,
    537                                                        &cStat,
    538                                                        &sSock,
    539                                                        plContext));
    540    }
    541 
    542    PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext));
    543 
    544    PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext));
    545 
    546    serverState = SERVER_LISTENING;
    547 
    548    PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_FALSE, timeout, &clientNetAddr, &cStat, &cSock, plContext));
    549 
    550    PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext));
    551 
    552    if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) {
    553        clientState = CLIENT_WAITFORCONNECT;
    554    } else {
    555        clientState = CLIENT_SEND1;
    556    }
    557 
    558    dispatcher();
    559 
    560 cleanup:
    561 
    562    PKIX_TEST_DECREF_AC(sSock);
    563    PKIX_TEST_DECREF_AC(cSock);
    564    PKIX_TEST_DECREF_AC(rendezvousSock);
    565 
    566    PKIX_TEST_RETURN();
    567 
    568    endTests("Socket");
    569 
    570    return (0);
    571 }