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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: test_ncbi_dsock.c,v $
  4.  * PRODUCTION Revision 1000.1  2004/02/12 21:56:23  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [CORE_001] Dev-tree R6.14
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: test_ncbi_dsock.c,v 1000.1 2004/02/12 21:56:23 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:  Anton Lavrentiev
  35.  *
  36.  * File Description:
  37.  *   Test suite for datagram socket API
  38.  *
  39.  */
  40. #include "../ncbi_ansi_ext.h"
  41. #include "../ncbi_priv.h"               /* CORE logging facilities */
  42. #include <connect/ncbi_connutil.h>
  43. #include <connect/ncbi_socket.h>
  44. #include <errno.h>
  45. #include <stdlib.h>
  46. #include <time.h>
  47. #ifdef NCBI_OS_UNIX
  48. #  include <unistd.h>
  49. #endif /*NCBI_OS_UNIX*/
  50. /* This header must go last */
  51. #include "test_assert.h"
  52. #if defined(NCBI_OS_BSD) || defined(NCBI_OS_OSF1) || defined(NCBI_OS_DARWIN)
  53.    /* FreeBSD has this limit :-/ Source: `sysctl net.inet.udp.maxdgram` */
  54.    /* For OSF1 (and FreeBSD) see also: /usr/include/netinet/udp_var.h   */
  55. #  define MAX_DGRAM_SIZE (9*1024)
  56. #elif defined(NCBI_OS_IRIX)
  57.    /* This has been found experimentally on IRIX64 6.5 04101931 IP25 */
  58. #  define MAX_DGRAM_SIZE (60*1024)
  59. #elif defined(NCBI_OS_LINUX)
  60. /* Larger sizes do not seem to work everywhere */
  61. #  define MAX_DGRAM_SIZE 65000
  62. #else
  63.    /* This is the maximal datagram size defined by the UDP standard */
  64. #  define MAX_DGRAM_SIZE 65535
  65. #endif
  66. #define DEFAULT_PORT 55555
  67. static int s_Usage(const char* prog)
  68. {
  69.     CORE_LOGF(eLOG_Error, ("Usage:n%s {client|server} [port [seed]]", prog));
  70.     return 1;
  71. }
  72. static int s_Server(int x_port)
  73. {
  74.     char           addr[32];
  75.     char*          buf;
  76.     SOCK           server;
  77.     EIO_Status     status;
  78.     STimeout       timeout;
  79.     unsigned int   peeraddr;
  80.     unsigned short peerport, port;
  81.     size_t         msglen, n, len;
  82.     char           minibuf[255];
  83.     if (x_port <= 0) {
  84.         CORE_LOG(eLOG_Error, "[Server]  Port wrongly specified");
  85.         return 1;
  86.     }
  87.     port = (unsigned short) x_port;
  88.     CORE_LOGF(eLOG_Note, ("[Server]  Opening DSOCK on port %hu", port));
  89.     if ((status = DSOCK_Create(&server)) != eIO_Success) {
  90.         CORE_LOGF(eLOG_Error, ("[Server]  Error creating DSOCK: %s",
  91.                                IO_StatusStr(status)));
  92.         return 1;
  93.     }
  94.     if ((status = DSOCK_Bind(server, port)) != eIO_Success) {
  95.         CORE_LOGF(eLOG_Error, ("[Server]  Error binding DSOCK to port %hu: %s",
  96.                                port, IO_StatusStr(status)));
  97.         return 1;
  98.     }
  99.     for (;;) {
  100.         if ((status = DSOCK_WaitMsg(server, 0/*infinite*/)) != eIO_Success) {
  101.             CORE_LOGF(eLOG_Error, ("[Server]  Error waiting on DSOCK: %s",
  102.                                    IO_StatusStr(status)));
  103.             break;
  104.         }
  105.         timeout.sec  = 0;
  106.         timeout.usec = 0;
  107.         if ((status = SOCK_SetTimeout(server, eIO_Read, &timeout))
  108.             != eIO_Success) {
  109.             CORE_LOGF(eLOG_Error, ("[Server]  Error setting zero read tmo: %s",
  110.                                    IO_StatusStr(status)));
  111.             break;
  112.         }
  113.         len = (size_t)(((double) rand()/(double) RAND_MAX)*sizeof(minibuf));
  114.         if ((status = DSOCK_RecvMsg(server, minibuf, len, 0, &msglen,
  115.                                     &peeraddr, &peerport)) != eIO_Success) {
  116.             CORE_LOGF(eLOG_Error, ("[Server]  Error reading from DSOCK: %s",
  117.                                    IO_StatusStr(status)));
  118.             continue;
  119.         }
  120.         if (len > msglen)
  121.             len = msglen;
  122.         if (SOCK_ntoa(peeraddr, addr, sizeof(addr)) != 0)
  123.             strcpy(addr, "<unknown>");
  124.         CORE_LOGF(eLOG_Note, ("[Server]  Message received from %s:%hu, "
  125.                               "%lu bytes",
  126.                               addr, peerport, (unsigned long) msglen));
  127.         if (!(buf = (char*) malloc(msglen ? msglen : 1))) {
  128.             CORE_LOG_ERRNO(eLOG_Error, errno,"[Server]  Cannot alloc msg buf");
  129.             break;
  130.         }
  131.         if (len)
  132.             memcpy(buf, minibuf, len);
  133.         while (len < msglen) {
  134.             n = (size_t)(((double)rand()/(double)RAND_MAX)*(msglen-len) + 0.5);
  135.             if ((status = SOCK_Read(server, buf + len, n, &n, eIO_ReadPlain))
  136.                 != eIO_Success) {
  137.                 CORE_LOGF(eLOG_Error,("[Server]  Error reading msg @ byte %lu:"
  138.                                       " %s", (unsigned long) len,
  139.                                       IO_StatusStr(status)));
  140.                 free(buf);
  141.                 continue;
  142.             }
  143.             len += n;
  144.         }
  145.         assert(SOCK_Read(server, 0, 1, &n, eIO_ReadPlain) == eIO_Closed);
  146.         CORE_LOG(eLOG_Note, "[Server]  Bouncing the message to sender");
  147.         timeout.sec  = 1;
  148.         timeout.usec = 0;
  149.         if ((status = SOCK_SetTimeout(server, eIO_Write, &timeout))
  150.             != eIO_Success){
  151.             CORE_LOGF(eLOG_Error, ("[Server]  Error setting write tmo: %s",
  152.                                    IO_StatusStr(status)));
  153.             break;
  154.         }
  155.         for (len = 0; len < msglen; len += n) {
  156.             n = (size_t)(((double)rand()/(double)RAND_MAX)*(msglen-len) + 0.5);
  157.             if ((status = SOCK_Write(server, buf + len, n, &n, eIO_WritePlain))
  158.                 != eIO_Success) {
  159.                 CORE_LOGF(eLOG_Error,("[Server]  Error writing msg @ byte %lu:"
  160.                                       " %s", (unsigned long) len,
  161.                                       IO_StatusStr(status)));
  162.                 break;
  163.             }
  164.         }
  165.         free(buf);
  166.         if ((status = DSOCK_SendMsg(server, addr, peerport, "--Reply--", 9))
  167.             != eIO_Success) {
  168.             CORE_LOGF(eLOG_Error, ("[Server]  Error sending to DSOCK: %s",
  169.                                    IO_StatusStr(status)));
  170.             /*continue*/;
  171.         }
  172.     }
  173.     /* On errors control reaches here */
  174.     if ((status = SOCK_Close(server)) != eIO_Success) {
  175.         CORE_LOGF(eLOG_Error, ("[Server]  Error closing DSOCK: %s",
  176.                                IO_StatusStr(status)));
  177.     }
  178.     return 1;
  179. }
  180. static int s_Client(int x_port, unsigned int max_try)
  181. {
  182.     size_t         msglen, n;
  183.     STimeout       timeout;
  184.     EIO_Status     status;
  185.     SOCK           client;
  186.     unsigned short port;
  187.     char*          buf;
  188.     unsigned long  id;
  189.     unsigned int   m;
  190.     if (x_port <= 0) {
  191.         CORE_LOG(eLOG_Error, "[Client]  Port wrongly specified");
  192.         return 1;
  193.     }
  194.  
  195.     port = (unsigned short) x_port;
  196.     CORE_LOGF(eLOG_Note, ("[Client]  Opening DSOCK on port %hu", port));
  197.     if ((status = DSOCK_Create(&client)) != eIO_Success) {
  198.         CORE_LOGF(eLOG_Error, ("[Client]  Error creating DSOCK: %s",
  199.                                IO_StatusStr(status)));
  200.         return 1;
  201.     }
  202.     msglen = (size_t)(((double)rand()/(double)RAND_MAX)*(MAX_DGRAM_SIZE - 10));
  203.     if (msglen < sizeof(time_t))
  204.         msglen = sizeof(time_t);
  205.     CORE_LOGF(eLOG_Note, ("[Client]  Generating a message %lu bytes long",
  206.                           (unsigned long) msglen));
  207.     if (!(buf = (char*) malloc(2*msglen + 9))) {
  208.         CORE_LOG_ERRNO(eLOG_Error, errno, "[Client]  Cannot alloc msg buf");
  209.         return 1;
  210.     }
  211.     for (n = sizeof(unsigned long); n < msglen; n++)
  212.         buf[n] = rand() % 0xFF;
  213.     id = (unsigned long) time(0);
  214.     for (m = 1; m <= max_try; m++) {
  215.         unsigned long tmp;
  216.         if (m != 1)
  217.             CORE_LOGF(eLOG_Note, ("[Client]  Attempt #%u", (unsigned int) m));
  218.         id++;
  219.         *((unsigned long*) buf) = SOCK_htonl((unsigned long) id);
  220.         if ((status = DSOCK_SendMsg(client, "127.0.0.1", port, buf, msglen))
  221.             != eIO_Success) {
  222.             CORE_LOGF(eLOG_Error, ("[Client]  Error sending to DSOCK: %s",
  223.                                    IO_StatusStr(status)));
  224.             return 1;
  225.         }
  226.         timeout.sec  = 1;
  227.         timeout.usec = 0;
  228.         if ((status = SOCK_SetTimeout(client, eIO_Read, &timeout))
  229.             != eIO_Success) {
  230.             CORE_LOGF(eLOG_Error, ("[Client]  Error setting read timeout: %s",
  231.                                    IO_StatusStr(status)));
  232.             return 1;
  233.         }
  234.     again:
  235.         if ((status = DSOCK_RecvMsg(client, &buf[msglen], msglen+9,0, &n, 0,0))
  236.             != eIO_Success) {
  237.             CORE_LOGF(eLOG_Error, ("[Client]  Error reading from DSOCK: %s",
  238.                                    IO_StatusStr(status)));
  239.             continue;
  240.         }
  241.         if (n != msglen + 9) {
  242.             CORE_LOGF(eLOG_Error, ("[Client]  Received message of wrong size: "
  243.                                    "%lu", (unsigned long) n));
  244.             return 1;
  245.         }
  246.         memcpy(&tmp, &buf[msglen], sizeof(tmp));
  247.         if (SOCK_ntohl(tmp) != id) {
  248.             m++;
  249.             CORE_LOGF(m < max_try ? eLOG_Warning : eLOG_Error,
  250.                       ("[Client]  Stale message received%s",
  251.                        m <= max_try ? ", reattempting to fetch" : ""));
  252.             if (m <= max_try)
  253.                 goto again;
  254.             break;
  255.         }
  256.         CORE_LOGF(eLOG_Note, ("[Client]  Received the message back, %lu bytes",
  257.                               (unsigned long) n));
  258.         assert(SOCK_Read(client, 0, 1, &n, eIO_ReadPlain) == eIO_Closed);
  259.         break;
  260.     }
  261.     if (m > max_try)
  262.         return 1;
  263.     for (n = sizeof(unsigned long); n < msglen; n++) {
  264.         if (buf[n] != buf[msglen + n])
  265.             break;
  266.     }
  267.     if (n < msglen) {
  268.         CORE_LOGF(eLOG_Error, ("[Client]  Bounced message corrupted, off=%lu",
  269.                                (unsigned long) n));
  270.         return 1;
  271.     }
  272.     if (strncmp(&buf[msglen*2], "--Reply--", 9) != 0) {
  273.         CORE_LOGF(eLOG_Error, ("[Client]  No signature in the message: %.9s",
  274.                                &buf[msglen*2]));
  275.         return 1;
  276.     }
  277.     free(buf);
  278.     if ((status = SOCK_Close(client)) != eIO_Success) {
  279.         CORE_LOGF(eLOG_Error, ("[Client]  Error closing DSOCK: %s",
  280.                                IO_StatusStr(status)));
  281.         return 1;
  282.     }
  283.     CORE_LOG(eLOG_Note, "[Client]  Completed successfully");
  284.     return 0;
  285. }
  286. int main(int argc, const char* argv[])
  287. {
  288.     unsigned long seed;
  289.     unsigned int  max_try = DEF_CONN_MAX_TRY;
  290.     const char*   env = getenv("CONN_DEBUG_PRINTOUT");
  291.     CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
  292.                            fLOG_OmitNoteLevel | fLOG_DateTime);
  293.     CORE_SetLOGFILE(stderr, 0/*false*/);
  294.     if (argc < 2 || argc > 4)
  295.         return s_Usage(argv[0]);
  296.     if (argc <= 3) {
  297. #ifdef NCBI_OS_UNIX
  298.         seed = (unsigned long) time(0) + (unsigned long) getpid();
  299. #else
  300.         seed = (unsigned long) time(0);
  301. #endif /*NCBI_OS_UNIX*/
  302.     } else
  303.         sscanf(argv[3], "%lu", &seed);
  304.     CORE_LOGF(eLOG_Note, ("Random SEED = %lu", seed));
  305.     srand(seed);
  306.     if (env && (strcasecmp(env, "1") == 0     ||
  307.                 strcasecmp(env, "yes") == 0   ||
  308.                 strcasecmp(env, "true") == 0  ||
  309.                 strcasecmp(env, "some") == 0  ||
  310.                 strcasecmp(env, "data") == 0)) {
  311.         SOCK_SetDataLoggingAPI(eOn);
  312.     }
  313.     if (!(env = getenv("CONN_MAX_TRY"))  ||  !(max_try = atoi(env)))
  314.         max_try = DEF_CONN_MAX_TRY;
  315.     if (strcasecmp(argv[1], "client") == 0)
  316.         return s_Client(argv[2] ? atoi(argv[2]) : DEFAULT_PORT, max_try);
  317.     if (strcasecmp(argv[1], "server") == 0)
  318.         return s_Server(argv[2] ? atoi(argv[2]) : DEFAULT_PORT);
  319.     return s_Usage(argv[0]);
  320. }
  321. /*
  322.  * --------------------------------------------------------------------------
  323.  * $Log: test_ncbi_dsock.c,v $
  324.  * Revision 1000.1  2004/02/12 21:56:23  gouriano
  325.  * PRODUCTION: UPGRADED [CORE_001] Dev-tree R6.14
  326.  *
  327.  * Revision 6.14  2003/12/11 15:34:29  lavr
  328.  * Lower maximal datagram size for Linux - 65535 didn't seem to work everywhere
  329.  *
  330.  * Revision 6.13  2003/12/10 17:24:16  lavr
  331.  * Reattempt to send/receive a datagram on I/O errors in client
  332.  *
  333.  * Revision 6.12  2003/10/27 19:00:32  lavr
  334.  * Limit datagram size for Darwin (which is BSD based)
  335.  *
  336.  * Revision 6.11  2003/05/29 18:03:06  lavr
  337.  * Changed one client's message
  338.  *
  339.  * Revision 6.10  2003/05/14 03:58:43  lavr
  340.  * Match changes in respective APIs of the tests
  341.  *
  342.  * Revision 6.9  2003/04/30 17:04:01  lavr
  343.  * Conformance to slightly modified datagram socket API
  344.  *
  345.  * Revision 6.8  2003/03/25 15:07:21  lavr
  346.  * Protect macros' values by enclosing in parentheses
  347.  *
  348.  * Revision 6.7  2003/03/25 15:04:13  lavr
  349.  * Add IRIX-specific datagram size limit (60K)
  350.  *
  351.  * Revision 6.6  2003/02/28 14:46:36  lavr
  352.  * Explicit casts for malloc()'ed memory
  353.  *
  354.  * Revision 6.5  2003/02/14 15:41:26  lavr
  355.  * Limit packet size on OSF1, too
  356.  *
  357.  * Revision 6.4  2003/02/06 04:34:28  lavr
  358.  * Do not exceed maximal dgram size on BSD; trickier readout in s_Server()
  359.  *
  360.  * Revision 6.3  2003/02/04 22:04:47  lavr
  361.  * Protection from truncation to 0 in double->int conversion
  362.  *
  363.  * Revision 6.2  2003/01/17 01:26:44  lavr
  364.  * Test improved/extended
  365.  *
  366.  * Revision 6.1  2003/01/16 16:33:06  lavr
  367.  * Initial revision
  368.  *
  369.  * ==========================================================================
  370.  */