test_ncbi_socket.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:33k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: test_ncbi_socket.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 17:06:50  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.21
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: test_ncbi_socket.c,v 1000.0 2003/10/29 17:06:50 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Denis Vakatov
  35.  *
  36.  * File Description:
  37.  *   Test suite for "ncbi_socket.[ch]", the portable TCP/IP socket API
  38.  *
  39.  */
  40. #include "../ncbi_config.h"
  41. /* OS must be specified in the command-line ("-D....") or in the conf. header
  42.  */
  43. #if !defined(NCBI_OS_UNIX) && !defined(NCBI_OS_MSWIN) && !defined(NCBI_OS_MAC)
  44. #  error "Unknown OS, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN, NCBI_OS_MAC!"
  45. #endif
  46. #include <connect/ncbi_socket.h>
  47. #include <connect/ncbi_util.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #if defined(NCBI_OS_UNIX)
  51. #  include <unistd.h>
  52. #  define X_SLEEP(x) ((void) sleep(x))
  53. #elif defined(NCBI_OS_MSWIN)
  54. #  include <windows.h>
  55. #  define X_SLEEP(x) ((void) Sleep(1000 * x))
  56. #else
  57. #  define X_SLEEP(x) ((void) 0)
  58. #endif
  59. /* This header must go last */
  60. #include "test_assert.h"
  61. /* #define DO_CLIENT */
  62. /* #define DO_SERVER */
  63. #define TEST_BUFSIZE 8192
  64. /* exit server before sending the data expected by client(Test 1) */
  65. /*#define TEST_SRV1_SHUTDOWN*/
  66. #ifndef TEST_SRV1_SHUTDOWN
  67. /* exit server immediately after its first client is served(Test 1) */
  68. /*#define TEST_SRV1_ONCE*/
  69. #endif
  70. /* test SOCK_Reconnect() */
  71. #define DO_RECONNECT
  72. /* Log stream
  73.  */
  74. static FILE* log_fp;
  75. /* The simplest randezvous (a plain request-reply) test functions
  76.  *      "TEST__client_1(SOCK sock)"
  77.  *      "TEST__server_1(SOCK sock)"
  78.  */
  79. static const char s_C1[] = "C1";
  80. static const char s_M1[] = "M1";
  81. static const char s_S1[] = "S1";
  82. #define N_SUB_BLOB    10
  83. #define SUB_BLOB_SIZE 70000
  84. #define BIG_BLOB_SIZE (N_SUB_BLOB * SUB_BLOB_SIZE)
  85. static void TEST__client_1(SOCK sock)
  86. {
  87.     EIO_Status status;
  88.     size_t     n_io, n_io_done;
  89.     char       buf[TEST_BUFSIZE];
  90.     fprintf(log_fp, "[INFO] TEST__client_1(TC1)n");
  91.     /* Send a short string */
  92.     SOCK_SetDataLoggingAPI(eOn);
  93.     {{
  94. #if defined(NCBI_OS_MAC)
  95.         /* Special treatment for MAC clients -- server not to
  96.          * shutdown the socket on writing. MAC library
  97.          * mistakingly assumes that if server is shutdown on writing then
  98.          * it is shutdown on reading, too (?!). 
  99.          */
  100.         const char* x_C1 = s_M1;
  101. #else
  102.         const char* x_C1 = s_C1;
  103. #endif
  104.         n_io = strlen(x_C1) + 1;
  105.         status = SOCK_Write(sock, x_C1, n_io, &n_io_done, eIO_WritePersist);
  106.     }}
  107.     assert(status == eIO_Success  &&  n_io == n_io_done);
  108.     /* Read the string back (it must be bounced by the server) */
  109.     SOCK_SetDataLoggingAPI(eOff);
  110.     SOCK_SetDataLogging(sock, eOn);
  111.     n_io = strlen(s_S1) + 1;
  112.     status = SOCK_Read(sock, buf, n_io, &n_io_done, eIO_ReadPeek);
  113.     status = SOCK_Read(sock, buf, n_io, &n_io_done, eIO_ReadPlain);
  114.     if (status == eIO_Closed) {
  115.         fprintf(log_fp, "[WARNING] TC1:: connection closedn");
  116.         assert(0);
  117.     }
  118.     assert(status == eIO_Success  &&  n_io == n_io_done);
  119.     assert(strcmp(buf, s_S1) == 0);
  120.     assert(SOCK_PushBack(sock, buf, n_io_done) == eIO_Success);
  121.     memset(buf, 'xFF', n_io_done);
  122.     assert(SOCK_Read(sock, buf, n_io_done, &n_io_done, eIO_ReadPlain)
  123.            == eIO_Success);
  124.     assert(SOCK_Status(sock, eIO_Read) == eIO_Success);
  125.     assert(strcmp(buf, s_S1) == 0);
  126.     SOCK_SetDataLoggingAPI(eDefault);
  127.     SOCK_SetDataLogging(sock, eDefault);
  128.     /* Send a very big binary blob */
  129.     {{
  130.         size_t i;
  131.         unsigned char* blob = (unsigned char*) malloc(BIG_BLOB_SIZE);
  132.         for (i = 0;  i < BIG_BLOB_SIZE;  blob[i] = (unsigned char) i, i++)
  133.             continue;
  134.         for (i = 0;  i < 10;  i++) {
  135.             status = SOCK_Write(sock, blob + i * SUB_BLOB_SIZE, SUB_BLOB_SIZE,
  136.                                 &n_io_done, eIO_WritePersist);
  137.             assert(status == eIO_Success  &&  n_io_done==SUB_BLOB_SIZE);
  138.         }
  139.         free(blob);
  140.     }}
  141.     /* Send a very big binary blob with read on write */
  142.     /* (it must be bounced by the server) */
  143.     {{
  144.         size_t i;
  145.         unsigned char* blob = (unsigned char*) malloc(BIG_BLOB_SIZE);
  146.         SOCK_SetReadOnWrite(sock, eOn);
  147.         for (i = 0;  i < BIG_BLOB_SIZE;  blob[i] = (unsigned char) i, i++)
  148.             continue;
  149.         for (i = 0;  i < 10;  i++) {
  150.             status = SOCK_Write(sock, blob + i * SUB_BLOB_SIZE, SUB_BLOB_SIZE,
  151.                                 &n_io_done, eIO_WritePersist);
  152.             assert(status == eIO_Success  &&  n_io_done == SUB_BLOB_SIZE);
  153.         }
  154.         /* Receive back a very big binary blob, and check its content */
  155.         memset(blob,0,BIG_BLOB_SIZE);
  156.         for (i = 0;  i < 10;  i++) {
  157.             status = SOCK_Read(sock, blob + i * SUB_BLOB_SIZE, SUB_BLOB_SIZE,
  158.                                &n_io_done, eIO_ReadPersist);
  159.             assert(status == eIO_Success  &&  n_io_done == SUB_BLOB_SIZE);
  160.         }
  161.         for (n_io = 0;  n_io < BIG_BLOB_SIZE;  n_io++)
  162.             assert(blob[n_io] == (unsigned char) n_io);
  163.         free(blob);
  164.     }}
  165.     /* Try to read more data (must hit EOF as the peer is shutdown) */
  166. #if !defined(NCBI_OS_MAC)
  167.     assert(SOCK_Read(sock, buf, 1, &n_io_done, eIO_ReadPeek)
  168.            == eIO_Closed);
  169.     assert(SOCK_Status(sock, eIO_Read) == eIO_Closed);
  170.     assert(SOCK_Read(sock, buf, 1, &n_io_done, eIO_ReadPlain)
  171.            == eIO_Closed);
  172.     assert(SOCK_Status(sock, eIO_Read) == eIO_Closed);
  173. #endif
  174.     /* Shutdown on read */
  175.     assert(SOCK_Shutdown(sock, eIO_Read)  == eIO_Success);
  176.     assert(SOCK_Status  (sock, eIO_Write) == eIO_Success);
  177.     assert(SOCK_Status  (sock, eIO_Read)  == eIO_Closed);
  178.     assert(SOCK_Read    (sock, 0, 0, &n_io_done, eIO_ReadPlain) == eIO_Closed);
  179.     assert(SOCK_Read    (sock, 0, 0, &n_io_done, eIO_ReadPeek)  == eIO_Closed);
  180.     assert(SOCK_Status  (sock, eIO_Read)  == eIO_Closed);
  181.     assert(SOCK_Status  (sock, eIO_Write) == eIO_Success);
  182.     assert(SOCK_Read    (sock, buf, 1,&n_io_done,eIO_ReadPlain) == eIO_Closed);
  183.     assert(SOCK_Read    (sock, buf, 1,&n_io_done,eIO_ReadPeek)  == eIO_Closed);
  184.     assert(SOCK_Status  (sock, eIO_Read)  == eIO_Closed);
  185.     assert(SOCK_Status  (sock, eIO_Write) == eIO_Success);
  186.     /* Shutdown on write */
  187.     assert(SOCK_Shutdown(sock, eIO_Write)          == eIO_Success);
  188.     assert(SOCK_Status  (sock, eIO_Write)          == eIO_Closed);
  189.     assert(SOCK_Write   (sock, 0, 0, &n_io_done, eIO_WritePersist)
  190.                                                    == eIO_Closed);
  191.     assert(SOCK_Status  (sock, eIO_Write)          == eIO_Closed);
  192.     assert(SOCK_Write   (sock, buf, 1, &n_io_done, eIO_WritePersist)
  193.                                                    == eIO_Closed);
  194.     assert(SOCK_Status  (sock, eIO_Write)          == eIO_Closed);
  195.     /* Double shutdown should be okay */
  196.     assert(SOCK_Shutdown(sock, eIO_Read)      == eIO_Success);
  197.     assert(SOCK_Shutdown(sock, eIO_ReadWrite) == eIO_Success);
  198.     assert(SOCK_Shutdown(sock, eIO_Write)     == eIO_Success);
  199.     assert(SOCK_Status  (sock, eIO_Read)      == eIO_Closed);
  200.     assert(SOCK_Status  (sock, eIO_Write)     == eIO_Closed);
  201.     assert(SOCK_Status  (sock, eIO_ReadWrite) == eIO_InvalidArg);
  202. }
  203. static void TEST__server_1(SOCK sock)
  204. {
  205.     EIO_Status status;
  206.     size_t     n_io, n_io_done;
  207.     char       buf[TEST_BUFSIZE];
  208.     fprintf(log_fp, "[INFO] TEST__server_1(TS1)n");
  209.     /* Receive and send back a short string */
  210.     SOCK_SetDataLogging(sock, eOn);
  211.     n_io = strlen(s_C1) + 1;
  212.     status = SOCK_Read(sock, buf, n_io, &n_io_done, eIO_ReadPlain);
  213.     assert(status == eIO_Success  &&  n_io == n_io_done);
  214.     assert(strcmp(buf, s_C1) == 0  ||  strcmp(buf, s_M1) == 0);
  215. #ifdef TEST_SRV1_SHUTDOWN
  216.     return 212;
  217. #endif
  218.     SOCK_SetDataLogging(sock, eDefault);
  219.     SOCK_SetDataLoggingAPI(eOn);
  220.     n_io = strlen(s_S1) + 1;
  221.     status = SOCK_Write(sock, s_S1, n_io, &n_io_done, eIO_WritePersist);
  222.     assert(status == eIO_Success  &&  n_io == n_io_done);
  223.     SOCK_SetDataLoggingAPI(eOff);
  224.     /* Receive a very big binary blob, and check its content */
  225.     {{
  226. #define DO_LOG_SIZE    300
  227. #define DONT_LOG_SIZE  BIG_BLOB_SIZE - DO_LOG_SIZE
  228.         unsigned char* blob = (unsigned char*) malloc(BIG_BLOB_SIZE);
  229.         status = SOCK_Read(sock,blob,DONT_LOG_SIZE,&n_io_done,eIO_ReadPersist);
  230.         assert(status == eIO_Success  &&  n_io_done == DONT_LOG_SIZE);
  231.         SOCK_SetDataLogging(sock, eOn);
  232.         status = SOCK_Read(sock, blob + DONT_LOG_SIZE, DO_LOG_SIZE,
  233.                            &n_io_done, eIO_ReadPersist);
  234.         assert(status == eIO_Success  &&  n_io_done == DO_LOG_SIZE);
  235.         SOCK_SetDataLogging(sock, eDefault);
  236.         SOCK_SetDataLoggingAPI(eDefault);
  237.         for (n_io = 0;  n_io < BIG_BLOB_SIZE;  n_io++)
  238.             assert(blob[n_io] == (unsigned char) n_io);
  239.         free(blob);
  240.     }}
  241.     /* Receive a very big binary blob, and write data back */
  242.     {{
  243. #define DO_LOG_SIZE    300
  244. #define DONT_LOG_SIZE  BIG_BLOB_SIZE - DO_LOG_SIZE
  245.         unsigned char* blob = (unsigned char*) malloc(BIG_BLOB_SIZE);
  246.         int i;
  247.         for (i = 0;  i < 10;  i++) {
  248.             /*            X_SLEEP(1);*/
  249.             status = SOCK_Read(sock, blob + i * SUB_BLOB_SIZE, SUB_BLOB_SIZE,
  250.                                &n_io_done, eIO_ReadPersist);
  251.             assert(status == eIO_Success  &&  n_io_done == SUB_BLOB_SIZE);
  252.             status = SOCK_Write(sock, blob + i * SUB_BLOB_SIZE, SUB_BLOB_SIZE,
  253.                                 &n_io_done, eIO_WritePersist);
  254.             assert(status == eIO_Success  &&  n_io_done == SUB_BLOB_SIZE);
  255.         }
  256.         for (n_io = 0;  n_io < BIG_BLOB_SIZE;  n_io++)
  257.             assert(blob[n_io] == (unsigned char) n_io);
  258.         free(blob);
  259.     }}
  260.     /* Shutdown on write */
  261. #ifdef NCBI_OS_MSWIN
  262.     assert(SOCK_Shutdown(sock, eIO_ReadWrite)    == eIO_Success);
  263. #else
  264.     assert(SOCK_Shutdown(sock, eIO_Write)        == eIO_Success);
  265. #endif
  266.     assert(SOCK_Status  (sock, eIO_Write)        == eIO_Closed);
  267.     assert(SOCK_Write   (sock, 0, 0, &n_io_done, eIO_WritePersist)
  268.                                                  == eIO_Closed);
  269.     assert(SOCK_Status  (sock, eIO_Write)        == eIO_Closed);
  270. #ifdef NCBI_OS_MSWIN
  271.     assert(SOCK_Status  (sock, eIO_Read)         == eIO_Closed);
  272. #else
  273.     assert(SOCK_Status  (sock, eIO_Read)         == eIO_Success);
  274. #endif
  275. }
  276. /* More complicated randezvous test functions
  277.  *      "TEST__client_2(SOCK sock)"
  278.  *      "TEST__server_2(SOCK sock)"
  279.  */
  280. static void s_DoubleTimeout(STimeout *to) {
  281.     if (!to->sec  &&  !to->usec) {
  282.         to->usec = 1;
  283.     } else {
  284.         to->sec   = 2 * to->sec + (2 * to->usec) / 1000000;
  285.         to->usec = (2 * to->usec) % 1000000;
  286.     }
  287. }
  288. static void TEST__client_2(SOCK sock)
  289. {
  290. #define W_FIELD  10
  291. #define N_FIELD  1000
  292. #define N_REPEAT 10
  293. #define N_RECONNECT 3
  294.     EIO_Status status;
  295.     size_t     n_io, n_io_done, i;
  296.     char       buf[W_FIELD * N_FIELD + 1];
  297.     fprintf(log_fp, "[INFO] TEST__client_2(TC2)n");
  298.     /* fill out a buffer to send to server */
  299.     memset(buf, 0, sizeof(buf));
  300.     for (i = 0;  i < N_FIELD;  i++) {
  301.         sprintf(buf + i * W_FIELD, "%10lu", (unsigned long)i);
  302.     }
  303.     /* send the buffer to server, then get it back */
  304.     for (i = 0;  i < N_REPEAT;  i++) {
  305.         char        buf1[sizeof(buf)];
  306.         STimeout    w_to, r_to;
  307.         int/*bool*/ w_timeout_on = (int)(i%2); /* if to start from     */
  308.         int/*bool*/ r_timeout_on = (int)(i%3); /* zero or inf. timeout */
  309.         char*       x_buf;
  310.         /* set timeout */
  311.         w_to.sec  = 0;
  312.         w_to.usec = 0;
  313.         status = SOCK_SetTimeout(sock, eIO_Write, w_timeout_on ? &w_to : 0);
  314.         assert(status == eIO_Success);
  315. #ifdef DO_RECONNECT
  316.         /* reconnect */
  317.         if ((i % N_RECONNECT) == 0) {
  318.             size_t j = i / N_RECONNECT;
  319.             do {
  320.                 status = SOCK_Reconnect(sock, 0, 0, 0);
  321.                 fprintf(log_fp,
  322.                         "[INFO] TEST__client_2::reconnect: i=%lu, status=%sn",
  323.                         (unsigned long)i, IO_StatusStr(status));
  324.                 assert(status == eIO_Success);
  325.                 assert(SOCK_Status(sock, eIO_Read)  == eIO_Success);
  326.                 assert(SOCK_Status(sock, eIO_Write) == eIO_Success);
  327.                 /* give a break to let server reset the listening socket */
  328.                 X_SLEEP(1);
  329.             } while ( j-- );
  330.         }
  331. #endif
  332.         /* send */
  333.         x_buf = buf;
  334.         n_io = sizeof(buf);
  335.         do {
  336.             X_SLEEP(1);
  337.             status = SOCK_Write(sock, x_buf, n_io,
  338.                                 &n_io_done, eIO_WritePersist);
  339.             if (status == eIO_Closed) {
  340.                 fprintf(log_fp,
  341.                         "[ERROR] TC2::write: connection closedn");
  342.                 assert(0);
  343.             }
  344.             fprintf(log_fp, "[INFO] TC2::write "
  345.                     "i=%d, status=%7s, n_io=%5lu, n_io_done=%5lu"
  346.                     "ntimeout(%d): %5lu sec, %6lu msecn",
  347.                     (int)i, IO_StatusStr(status),
  348.                     (unsigned long)n_io, (unsigned long)n_io_done,
  349.                     (int)w_timeout_on,
  350.                     (unsigned long)w_to.sec, (unsigned long)w_to.usec);
  351.             if ( !w_timeout_on ) {
  352.                 assert(status == eIO_Success  &&  n_io_done == n_io);
  353.             } else {
  354.                 const STimeout* x_to;
  355.                 assert(status == eIO_Success  ||  status == eIO_Timeout);
  356.                 x_to = SOCK_GetTimeout(sock, eIO_Write);
  357.                 assert(w_to.sec == x_to->sec  &&  w_to.usec == x_to->usec);
  358.             }
  359.             n_io  -= n_io_done;
  360.             x_buf += n_io_done;
  361.             if (status == eIO_Timeout)
  362.                 s_DoubleTimeout(&w_to);
  363.             status = SOCK_SetTimeout(sock, eIO_Write, &w_to);
  364.             assert(status == eIO_Success);
  365.             w_timeout_on = 1/*true*/;
  366.         } while ( n_io );
  367.         /* get back the just sent data */
  368.         r_to.sec  = 0;
  369.         r_to.usec = 0;
  370.         status = SOCK_SetTimeout(sock, eIO_Read, (r_timeout_on ? &r_to : 0));
  371.         assert(status == eIO_Success);
  372.         x_buf = buf1;
  373.         n_io = sizeof(buf1);
  374.         do {
  375.             if (i%2 == 0) {
  376.                 /* peek a little piece twice and compare */
  377.                 char   xx_buf1[128], xx_buf2[128];
  378.                 size_t xx_io_done1, xx_io_done2;
  379.                 if (SOCK_Read(sock, xx_buf1, sizeof(xx_buf1), &xx_io_done1,
  380.                               eIO_ReadPeek) == eIO_Success  &&
  381.                     SOCK_Read(sock, xx_buf2, xx_io_done1, &xx_io_done2,
  382.                               eIO_ReadPeek) == eIO_Success) {
  383.                     assert(xx_io_done1 >= xx_io_done2);
  384.                     assert(memcmp(xx_buf1, xx_buf2, xx_io_done2) == 0);
  385.                 }
  386.             }
  387.             status = SOCK_Read(sock, x_buf, n_io, &n_io_done, eIO_ReadPlain);
  388.             if (status == eIO_Closed) {
  389.                 fprintf(log_fp,
  390.                         "[ERROR] TC2::read: connection closedn");
  391.                 assert(SOCK_Status(sock, eIO_Read) == eIO_Closed);
  392.                 assert(0);
  393.             }
  394.             fprintf(log_fp, "[INFO] TC2::read: "
  395.                     "i=%d, status=%7s, n_io=%5lu, n_io_done=%5lu"
  396.                     "ntimeout(%d): %5u sec, %6u usecn",
  397.                     (int)i, IO_StatusStr(status),
  398.                     (unsigned long)n_io, (unsigned long)n_io_done,
  399.                     (int)r_timeout_on, r_to.sec, r_to.usec);
  400.             if ( !r_timeout_on ) {
  401.                 assert(status == eIO_Success  &&  n_io_done > 0);
  402.             } else {
  403.                 const STimeout* x_to;
  404.                 assert(status == eIO_Success  ||  status == eIO_Timeout);
  405.                 x_to = SOCK_GetTimeout(sock, eIO_Read);
  406.                 assert(r_to.sec == x_to->sec  &&  r_to.usec == x_to->usec);
  407.             }
  408.             n_io  -= n_io_done;
  409.             x_buf += n_io_done;
  410.             if (status == eIO_Timeout)
  411.                 s_DoubleTimeout(&r_to);
  412.             status = SOCK_SetTimeout(sock, eIO_Read, &r_to);
  413.             assert(status == eIO_Success);
  414.             r_timeout_on = 1/*true*/;
  415.         } while ( n_io );
  416.         assert(memcmp(buf, buf1, sizeof(buf)) == 0);
  417.     }
  418. }
  419. static void TEST__server_2(SOCK sock, LSOCK lsock)
  420. {
  421.     EIO_Status status;
  422.     size_t     n_io, n_io_done;
  423.     char       buf[TEST_BUFSIZE];
  424.     STimeout   r_to, w_to, rc_to;
  425.     size_t     i;
  426.     fprintf(log_fp, "[INFO] TEST__server_2(TS2)n");
  427.     r_to.sec   = 0;
  428.     r_to.usec  = 0;
  429.     w_to = r_to;
  430.     rc_to.sec  = 30;
  431.     rc_to.usec = 123456;
  432.     /* goto */
  433.  l_reconnect: /* reconnection loopback */
  434.     status = SOCK_SetTimeout(sock, eIO_Read,  &r_to);
  435.     assert(status == eIO_Success);
  436.     status = SOCK_SetTimeout(sock, eIO_Write, &w_to);
  437.     assert(status == eIO_Success);
  438.     for (i = 0;  ;  i++) {
  439.         char* x_buf;
  440.         /* read data from socket */
  441.         n_io = sizeof(buf);
  442.         status = SOCK_Read(sock, buf, n_io, &n_io_done, eIO_ReadPlain);
  443.         switch ( status ) {
  444.         case eIO_Success:
  445.             fprintf(log_fp, "[INFO] TS2::read: "
  446.                     "[%lu], status=%7s, n_io=%5lu, n_io_done=%5lun",
  447.                     (unsigned long)i, IO_StatusStr(status),
  448.                     (unsigned long)n_io, (unsigned long)n_io_done);
  449.             assert(n_io_done > 0);
  450.             break;
  451.         case eIO_Closed:
  452.             fprintf(log_fp, "[INFO] TS2::read: connection closedn");
  453.             assert(SOCK_Status(sock, eIO_Read) == eIO_Closed);
  454.             /* reconnect */
  455.             if ( !lsock )
  456.                 return;
  457.             fprintf(log_fp, "[INFO] TS2:: reconnectn");
  458.             SOCK_Close(sock);
  459.             if ((status = LSOCK_Accept(lsock, &rc_to, &sock)) != eIO_Success)
  460.                 return;
  461.             assert(SOCK_Status(sock, eIO_Read) == eIO_Success);
  462.             /* !!! */
  463.             goto l_reconnect;
  464.         case eIO_Timeout:
  465.             fprintf(log_fp, "[INFO] TS2::read: "
  466.                     "[%lu] timeout expired: %5u sec, %6u usecn",
  467.                     (unsigned long)i, r_to.sec, r_to.usec);
  468.             assert(n_io_done == 0);
  469.             s_DoubleTimeout(&r_to);
  470.             status = SOCK_SetTimeout(sock, eIO_Read, &r_to);
  471.             assert(status == eIO_Success);
  472.             assert(SOCK_Status(sock, eIO_Read) == eIO_Success);
  473.             break;
  474.         default:
  475.             assert(0);
  476.             return;
  477.         } /* switch */
  478.         /* write(just the same) data back to client */
  479.         n_io  = n_io_done;
  480.         x_buf = buf;
  481.         while ( n_io ) {
  482.             status = SOCK_Write(sock, buf, n_io, &n_io_done, eIO_WritePersist);
  483.             switch ( status ) {
  484.             case eIO_Success:
  485.                 fprintf(log_fp, "[INFO] TS2::write: "
  486.                         "[%lu], status=%7s, n_io=%5lu, n_io_done=%5lun",
  487.                         (unsigned long)i, IO_StatusStr(status),
  488.                         (unsigned long)n_io, (unsigned long)n_io_done);
  489.                 assert(n_io_done > 0);
  490.                 break;
  491.             case eIO_Closed:
  492.                 fprintf(log_fp, "[ERROR] TS2::write: connection closedn");
  493.                 assert(0);
  494.                 return;
  495.             case eIO_Timeout:
  496.                 fprintf(log_fp, "[INFO] TS2::write: "
  497.                         "[%lu] timeout expired: %5u sec, %6u usecn",
  498.                         (unsigned long)i, w_to.sec, w_to.usec);
  499.                 assert(n_io_done == 0);
  500.                 s_DoubleTimeout(&w_to);
  501.                 status = SOCK_SetTimeout(sock, eIO_Write, &w_to);
  502.                 assert(status == eIO_Success);
  503.                 break;
  504.             default:
  505.                 assert(0);
  506.                 return;
  507.             } /* switch */
  508.             n_io  -= n_io_done;
  509.             x_buf += n_io_done;
  510.         }
  511.     }
  512. }
  513. /* Skeletons for the socket i/o test:
  514.  *   TEST__client(...)
  515.  *   TEST__server(...)
  516.  *   establish and close connection;  call test i/o functions like
  517.  *     TEST__[client|server]_[1|2|...] (...)
  518.  */
  519. static void TEST__client(const char*     server_host,
  520.                          unsigned short  server_port,
  521.                          const STimeout* timeout)
  522. {
  523.     SOCK       sock;
  524.     EIO_Status status;
  525.     fprintf(log_fp, "[INFO] TEST__client(host = "%s", port = %hu, ",
  526.             server_host, server_port);
  527.     if ( timeout )
  528.         fprintf(log_fp, "timeout = %u.%u)n", timeout->sec, timeout->usec);
  529.     else
  530.         fprintf(log_fp, "timeout = INFINITE)n");
  531.     /* Connect to server */
  532.     status = SOCK_Create(server_host, server_port, timeout, &sock);
  533.     assert(status == eIO_Success);
  534.     /* Test the simplest randezvous(plain request-reply)
  535.      * The two peer functions are:
  536.      *      "TEST__[client|server]_1(SOCK sock)"
  537.      */
  538.     TEST__client_1(sock);
  539.     /* Test a more complex case
  540.      * The two peer functions are:
  541.      *      "TEST__[client|server]_2(SOCK sock)"
  542.      */
  543.     TEST__client_2(sock);
  544.     /* Close connection and exit */
  545.     status = SOCK_Close(sock);
  546.     assert(status == eIO_Success  ||  status == eIO_Closed);
  547. }
  548. static void TEST__server(unsigned short port)
  549. {
  550.     LSOCK      lsock;
  551.     EIO_Status status;
  552.     fprintf(log_fp, "[INFO] TEST__server(port = %hu)n", port);
  553.     /* Create listening socket */
  554.     status = LSOCK_Create(port, 1, &lsock);
  555.     assert(status == eIO_Success);
  556.     /* Accept connections from clients and run test sessions */
  557.     for (;;) {
  558.         /* Accept connection */
  559.         SOCK sock;
  560.         status = LSOCK_Accept(lsock, NULL, &sock);
  561.         assert(status == eIO_Success);
  562.         /* Test the simplest randezvous(plain request-reply)
  563.          * The two peer functions are:
  564.          *      "TEST__[client|server]_1(SOCK sock)"
  565.          */
  566.         TEST__server_1(sock);
  567.         /* Test a more complex case
  568.          * The two peer functions are:
  569.          *      "TEST__[client|server]_2(SOCK sock)"
  570.          */
  571. #ifdef DO_RECONNECT
  572.         TEST__server_2(sock, lsock);
  573. #else
  574.         TEST__server_2(sock, 0);
  575. #endif
  576.         /* Close connection */
  577.         status = SOCK_Close(sock);
  578.         assert(status == eIO_Success  ||  status == eIO_Closed);
  579. #ifdef TEST_SRV1_ONCE
  580.         /* Close listening socket */
  581.         assert(LSOCK_Close(lsock) == eIO_Success);
  582.         /* Finish after the first session */
  583.         break;
  584. #endif
  585.     } /* for */
  586. }
  587. /* Consistency...
  588.  */
  589. #if defined(DO_SERVER)  &&  defined(DO_CLIENT)
  590. #  error "Only one of DO_SERVER, DO_CLIENT can be defined!"
  591. #endif
  592. /* Fake (printout only) MT critical section callback and data
  593.  */
  594. static char TEST_LockUserData[] = "TEST_LockUserData";
  595. #if defined(__cplusplus)
  596. extern "C" {
  597.     static int/*bool*/ TEST_LockHandler(void* user_data, EMT_Lock how);
  598.     static void        TEST_LockCleanup(void* user_data);
  599. }
  600. #endif /* __cplusplus */
  601. static int/*bool*/ TEST_LockHandler(void* user_data, EMT_Lock how)
  602. {
  603.     const char* what_str = 0;
  604.     switch ( how ) {
  605.     case eMT_Lock:
  606.         what_str = "eMT_Lock";
  607.         break;
  608.     case eMT_LockRead:
  609.         what_str = "eMT_LockRead";
  610.         break;
  611.     case eMT_Unlock:
  612.         what_str = "eMT_Unlock";
  613.         break;
  614.     }
  615.     fprintf(log_fp, "TEST_LockHandler("%s", %s)n",
  616.             user_data ? (char*)user_data : "<NULL>", what_str);
  617.     return 1/*true*/;
  618. }
  619. static void TEST_LockCleanup(void* user_data)
  620. {
  621.     fprintf(log_fp, "TEST_LockCleanup("%s")n",
  622.             user_data ? (char*)user_data : "<NULL>");
  623. }
  624. static int/*bool*/ TEST_gethostbyaddr(unsigned int host);
  625. static const char* s_ntoa(unsigned int host)
  626. {
  627.     static char buf[256];
  628.     if (SOCK_ntoa(host, buf, sizeof(buf)) != 0) {
  629.         buf[0] = '?';
  630.         buf[1] = '';
  631.     }
  632.     return buf;
  633. }
  634. static int/*bool*/ TEST_gethostbyname(const char* name)
  635. {
  636.     char         buf[256];
  637.     unsigned int host;
  638.     fprintf(log_fp, "------------n");
  639.     host = SOCK_gethostbyname(name);
  640.     fprintf(log_fp, "SOCK_gethostbyname("%s"):  0x%08X [%s]n",
  641.             name, (unsigned int) host, s_ntoa(host));
  642.     if ( !host ) {
  643.         return 0/*false*/;
  644.     }
  645.       
  646.     name = SOCK_gethostbyaddr(host, buf, sizeof(buf));
  647.     if ( name ) {
  648.         assert(name == buf);
  649.         assert(0 < strlen(buf)  &&  strlen(buf) < sizeof(buf));
  650.         fprintf(log_fp, "SOCK_gethostbyaddr(0x%08X [%s]):  "%s"n",
  651.                 (unsigned int) host, s_ntoa(host), name);
  652.     } else {
  653.         fprintf(log_fp, "SOCK_gethostbyaddr(0x%08X [%s]):  <not found>n",
  654.                 (unsigned int) host, s_ntoa(host));
  655.     }
  656.     return 1/*true*/;
  657. }
  658. static int/*bool*/ TEST_gethostbyaddr(unsigned int host)
  659. {
  660.     const char*  name;
  661.     char         buf[1024];
  662.     fprintf(log_fp, "- - - - - - -n");
  663.     name = SOCK_gethostbyaddr(host, buf, sizeof(buf));
  664.     if ( name ) {
  665.         assert(name == buf);
  666.         assert(0 < strlen(buf)  &&  strlen(buf) < sizeof(buf));
  667.         fprintf(log_fp, "SOCK_gethostbyaddr(0x%08X [%s]):  "%s"n",
  668.                 (unsigned int) host, s_ntoa(host), name);
  669.     } else {
  670.         fprintf(log_fp, "SOCK_gethostbyaddr(0x%08X [%s]):  <not found>n",
  671.                 (unsigned int) host, s_ntoa(host));
  672.         return 0/*false*/;
  673.     }
  674.     host = SOCK_gethostbyname(name);
  675.     fprintf(log_fp, "SOCK_gethostbyname("%s"):  0x%08X [%s]n",
  676.             name, (unsigned int) host, s_ntoa(host));
  677.       
  678.     return 1/*true*/;
  679. }
  680. /* Try SOCK_htonl(), SOCK_gethostbyname() and SOCK_gethostbyaddr()
  681.  */
  682. static void TEST_gethostby(void)
  683. {
  684.     fprintf(log_fp, "n===============================n");
  685.     assert( SOCK_htonl(0) == 0 );
  686.     assert( SOCK_htonl(0xFFFFFFFF) == 0xFFFFFFFF );
  687.     assert( !TEST_gethostbyname("  ") );
  688.     assert( !TEST_gethostbyname("a1....b1") );
  689.     assert( !TEST_gethostbyname("boo.foo.bar.doo") );
  690.     fprintf(log_fp, "n++++++++++++++++++++++n");
  691.     (void) TEST_gethostbyname("localhost");
  692.     (void) TEST_gethostbyname("ncbi.nlm.nih.gov");
  693.     (void) TEST_gethostbyname("127.0.0.1");
  694.     (void) TEST_gethostbyname("130.14.25.1");
  695.     (void) TEST_gethostbyaddr(0);
  696.     (void) TEST_gethostbyaddr(SOCK_gethostbyname("127.0.0.1"));
  697.     (void) TEST_gethostbyaddr(SOCK_gethostbyname("130.14.25.1"));
  698.     (void) TEST_gethostbyaddr(SOCK_gethostbyname("234.234.234.234"));
  699.     (void) TEST_gethostbyaddr(0xFFFFFFFF);
  700.     fprintf(log_fp, "n===============================n");
  701. }
  702. /* Main function
  703.  * Parse command-line options, initialize and cleanup API internals;
  704.  * run client or server test
  705.  */
  706. extern int main(int argc, char** argv)
  707. {
  708. #define MIN_PORT 5001
  709. #define DEF_PORT 5555
  710. #define DEF_HOST "localhost"
  711.     /* Error log stream */
  712.     log_fp = stderr;
  713.     /* Test client or server using hard-coded parameters */
  714. #if   defined(DO_SERVER)
  715.     argc = 2;
  716. #elif defined(DO_CLIENT)
  717.     argc = 3;
  718. #endif
  719.     /* Try to set various fake MT safety locks
  720.      */
  721.     CORE_SetLOCK( MT_LOCK_Create(0, TEST_LockHandler, TEST_LockCleanup) );
  722.     CORE_SetLOCK(0);
  723.     CORE_SetLOCK(0);
  724.     CORE_SetLOCK( MT_LOCK_Create(&TEST_LockUserData,
  725.                                  TEST_LockHandler, TEST_LockCleanup) );
  726.     /* Setup log stream
  727.      */
  728.     CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
  729.                            fLOG_OmitNoteLevel | fLOG_DateTime);
  730.     CORE_SetLOGFILE(stderr, 0/*false*/);
  731.     /* Printout local hostname
  732.      */
  733.     {{
  734.         char local_host[64];
  735.         assert(SOCK_gethostname(local_host, sizeof(local_host)) == 0);
  736.         fprintf(log_fp, "[INFO] Running NCBISOCK test on host "%s"n",
  737.                 local_host);
  738.     }}
  739.     /* Parse cmd.-line args and decide whether it's a client or a server
  740.      */
  741.     switch ( argc ) {
  742.     case 2: {
  743.         /*** SERVER ***/
  744.         int port;
  745. #if defined(DO_SERVER)
  746.         port = DEF_PORT;
  747. #else
  748.         if (sscanf(argv[1], "%d", &port) != 1  ||  port < MIN_PORT)
  749.             break;
  750. #endif /* DO_SERVER */
  751.         TEST__server((unsigned short) port);
  752.         assert(SOCK_ShutdownAPI() == eIO_Success);
  753.         CORE_SetLOG(0);
  754.         CORE_SetLOCK(0);
  755.         return 0;
  756.     }
  757.     case 3: case 4: {
  758.         /*** CLIENT ***/
  759.         const char* server_host;
  760.         int         server_port;
  761.         STimeout*   timeout = 0;
  762. #if defined(DO_CLIENT)
  763.         server_host = DEF_HOST;
  764.         server_port = DEF_PORT;
  765. #else
  766.         STimeout    x_timeout;
  767.         /* host */
  768.         server_host = argv[1];
  769.         /* port */
  770.         if (sscanf(argv[2], "%d", &server_port) != 1  ||
  771.             server_port < MIN_PORT)
  772.             break;
  773.         /* timeout */
  774.         if (argc == 4) {
  775.             double tm_out = atof(argv[3]);
  776.             if (tm_out < 0)
  777.                 break;
  778.             x_timeout.sec  = (unsigned int)tm_out;
  779.             x_timeout.usec = (unsigned int)((tm_out - x_timeout.sec) *1000000);
  780.             timeout = &x_timeout;
  781.         };
  782. #endif /* DO_CLIENT */
  783.         TEST_gethostby();
  784.         TEST__client(server_host, (unsigned short)server_port, timeout);
  785.         assert(SOCK_ShutdownAPI() == eIO_Success);
  786.         CORE_SetLOG(0);
  787.         CORE_SetLOCK(0);
  788.         return 0;
  789.     }
  790.     } /* switch */
  791.     /* USAGE
  792.      */
  793.     fprintf(log_fp,
  794.             "nUSAGE:n"
  795.             "  Client: %s <srv_host> <port> [conn_timeout]n"
  796.             "  Server: %s <port>n"
  797.             " where <port> is greater than %d, and [conn_timeout] is doublen",
  798.             argv[0], argv[0], (int)MIN_PORT);
  799.     CORE_SetLOG(0);
  800.     CORE_SetLOCK(0);
  801.     return 1;
  802. }
  803. /*
  804.  * ---------------------------------------------------------------------------
  805.  * $Log: test_ncbi_socket.c,v $
  806.  * Revision 1000.0  2003/10/29 17:06:50  gouriano
  807.  * PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.21
  808.  *
  809.  * Revision 6.21  2003/05/21 17:46:51  lavr
  810.  * Fix MSVC-related problems with SOCK_Shutdown()
  811.  *
  812.  * Revision 6.20  2003/05/14 03:58:43  lavr
  813.  * Match changes in respective APIs of the tests
  814.  *
  815.  * Revision 6.19  2002/12/04 16:58:13  lavr
  816.  * No changes
  817.  *
  818.  * Revision 6.18  2002/11/01 20:17:39  lavr
  819.  * Change hostname buffers to hold up to 256 chars
  820.  *
  821.  * Revision 6.17  2002/10/11 19:58:23  lavr
  822.  * Remove asserts() (replace with tests) for SOCK_gethostbyaddr({0|0xFFFFFFFF})
  823.  *
  824.  * Revision 6.16  2002/08/12 15:10:43  lavr
  825.  * Use persistent SOCK_Write()
  826.  *
  827.  * Revision 6.15  2002/08/07 16:38:08  lavr
  828.  * EIO_ReadMethod enums changed accordingly; log moved to end
  829.  *
  830.  * Revision 6.14  2002/03/22 19:47:48  lavr
  831.  * Test_assert.h made last among the include files
  832.  *
  833.  * Revision 6.13  2002/02/11 20:36:45  lavr
  834.  * Use "ncbi_config.h"
  835.  *
  836.  * Revision 6.12  2002/01/16 21:23:15  vakatov
  837.  * Utilize header "test_assert.h" to switch on ASSERTs in the Release mode too
  838.  *
  839.  * Revision 6.11  2001/07/11 00:44:33  vakatov
  840.  * Added TEST_gethostby***() -- tests for SOCK_gethostby{addr,name}()
  841.  *
  842.  * Revision 6.10  2001/05/21 15:11:13  ivanov
  843.  * Added test for automatic read on write data from the socket
  844.  * (stall protection).
  845.  *
  846.  * Revision 6.9  2001/01/26 23:55:10  vakatov
  847.  * [NCBI_OS_MAC]  Do not do server write shutdown for MAC client
  848.  *
  849.  * Revision 6.8  2000/11/15 18:51:44  vakatov
  850.  * Add tests for SOCK_Shutdown() and SOCK_Status().
  851.  * Use SOCK_Status() instead of SOCK_Eof().
  852.  *
  853.  * Revision 6.7  2000/06/23 19:39:22  vakatov
  854.  * Test the logging of socket I/O (incl. binary data)
  855.  *
  856.  * Revision 6.6  2000/03/24 23:12:13  vakatov
  857.  * Starting the development quasi-branch to implement CONN API.
  858.  * All development is performed in the NCBI C++ tree only, while
  859.  * the NCBI C tree still contains "frozen" (see the last revision) code.
  860.  *
  861.  * Revision 6.5  2000/02/24 23:09:42  vakatov
  862.  * Use C++ Toolkit specific wrapper "test_ncbi_socket_.c" for
  863.  * "test_ncbi_socket.c"
  864.  *
  865.  * Revision 6.4  2000/02/23 22:34:37  vakatov
  866.  * Can work both "standalone" and as a part of NCBI C++ or C toolkits
  867.  *
  868.  * Revision 6.3  1999/11/26 19:05:21  vakatov
  869.  * Initialize "log_fp" in "main()"...
  870.  *
  871.  * Revision 6.2  1999/10/19 16:16:03  vakatov
  872.  * Try the NCBI C and C++ headers only if NCBI_OS_{UNIX, MSWIN, MAC} is
  873.  * not #define'd
  874.  *
  875.  * Revision 6.1  1999/10/18 15:40:21  vakatov
  876.  * Initial revision
  877.  *
  878.  * ===========================================================================
  879.  */