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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbi_socket_connector.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 16:40:19  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.19
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbi_socket_connector.c,v 1000.0 2003/10/29 16:40:19 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, Anton Lavrentiev
  35.  *
  36.  * File Description:
  37.  *   Implement CONNECTOR for a network socket(based on the NCBI "SOCK").
  38.  *
  39.  *   See in "connectr.h" for the detailed specification of the underlying
  40.  *   connector("CONNECTOR", "SConnectorTag") methods and structures.
  41.  *
  42.  */
  43. #include "ncbi_ansi_ext.h"
  44. #include <connect/ncbi_socket_connector.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #define MAX_IP_ADDR_LEN       16 /* sizeof("255.255.255.255") */
  48. /***********************************************************************
  49.  *  INTERNAL -- Auxiliary types and static functions
  50.  ***********************************************************************/
  51. /* All internal data necessary to perform the (re)connect and i/o
  52.  */
  53. typedef struct {
  54.     SOCK           sock;      /* socket;  NULL if not connected yet       */
  55.     char*          host;      /* server:  host                            */
  56.     unsigned short port;      /* server:  service port                    */
  57.     unsigned int   max_try;   /* max.number of attempts to establish conn */
  58.     void*          init_data; /* data to send to the server on connect    */
  59.     size_t         init_size; /* size of the "inst_str" buffer            */
  60.     TSCC_Flags     flags;     /* see SOCK_CreateConnectorEx               */
  61. } SSockConnector;
  62. /***********************************************************************
  63.  *  INTERNAL -- "s_VT_*" functions for the "virt. table" of connector methods
  64.  ***********************************************************************/
  65. #ifdef __cplusplus
  66. extern "C" {
  67. #endif /* __cplusplus */
  68.     static const char* s_VT_GetType (CONNECTOR       connector);
  69.     static char*       s_VT_Descr   (CONNECTOR       connector);
  70.     static EIO_Status  s_VT_Open    (CONNECTOR       connector,
  71.                                      const STimeout* timeout);
  72.     static EIO_Status  s_VT_Wait    (CONNECTOR       connector,
  73.                                      EIO_Event       event,
  74.                                      const STimeout* timeout);
  75.     static EIO_Status  s_VT_Write   (CONNECTOR       connector,
  76.                                      const void*     buf,
  77.                                      size_t          size,
  78.                                      size_t*         n_written,
  79.                                      const STimeout* timeout);
  80.     static EIO_Status  s_VT_Read    (CONNECTOR       connector,
  81.                                      void*           buf,
  82.                                      size_t          size,
  83.                                      size_t*         n_read,
  84.                                      const STimeout* timeout);
  85.     static EIO_Status  s_VT_Status  (CONNECTOR       connector,
  86.                                      EIO_Event       dir);
  87.     static EIO_Status  s_VT_Close   (CONNECTOR       connector,
  88.                                      const STimeout* timeout);
  89.     static void        s_Setup      (SMetaConnector* meta,
  90.                                      CONNECTOR       connector);
  91.     static void        s_Destroy    (CONNECTOR       connector);
  92. #  ifdef IMPLEMENTED__CONN_WaitAsync
  93.     static EIO_Status s_VT_WaitAsync(void*                   connector,
  94.                                      FConnectorAsyncHandler  func,
  95.                                      SConnectorAsyncHandler* data);
  96. #  endif
  97. #ifdef __cplusplus
  98. } /* extern "C" */
  99. #endif /* __cplusplus */
  100. /*ARGSUSED*/
  101. static const char* s_VT_GetType
  102. (CONNECTOR connector)
  103. {
  104.     return "SOCK";
  105. }
  106. static char* s_VT_Descr
  107. (CONNECTOR connector)
  108. {
  109.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  110.     size_t len = strlen(xxx->host) + 6/*:port*/ + 1/*EOL*/;
  111.     char* buf = (char*) malloc(len);
  112.     if (buf)
  113.         sprintf(buf, "%s:%hu", xxx->host, xxx->port);
  114.     return buf;
  115. }
  116. static EIO_Status s_VT_Open
  117. (CONNECTOR       connector,
  118.  const STimeout* timeout)
  119. {
  120.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  121.     EIO_Status   status = eIO_Unknown;
  122.     unsigned int i = 0;
  123.     do {
  124.         if (xxx->sock && !xxx->host) {
  125.             /* on-top (connected) connector for the 1st time - only once here*/
  126.             unsigned int   host;
  127.             unsigned short port;
  128.             char           addr[MAX_IP_ADDR_LEN];
  129.             SOCK_GetPeerAddress(xxx->sock, &host, &port, eNH_HostByteOrder);
  130.             if (SOCK_ntoa(SOCK_htonl(host), addr, sizeof(addr)) != 0)
  131.                 return eIO_Unknown;
  132.             xxx->host = strdup(addr);
  133.             xxx->port = port;
  134.             status = eIO_Success;
  135.         } else {
  136.             if ( !xxx->max_try )
  137.                 break;
  138.             /* connect/reconnect */
  139.             status = xxx->sock ?
  140.                 SOCK_Reconnect(xxx->sock, 0, 0, timeout) :
  141.                 SOCK_CreateEx(xxx->host, xxx->port, timeout, &xxx->sock,
  142.                               xxx->init_data, xxx->init_size,
  143.                               (xxx->flags & eSCC_DebugPrintout)
  144.                               ? eOn : eDefault);
  145.             if (xxx->init_data) {
  146.                 free(xxx->init_data);
  147.                 xxx->init_data = 0;
  148.                 xxx->init_size = 0;
  149.             }
  150.             i++;
  151.         }
  152.         if (status == eIO_Success) {
  153.             SOCK_SetReadOnWrite(xxx->sock,
  154.                                 (xxx->flags & eSCC_SetReadOnWrite)
  155.                                 ? eOn : eDefault);
  156.             break;
  157.         }
  158.         /* error: continue trying */
  159.     } while (i < xxx->max_try);
  160.     return status;
  161. }
  162. static EIO_Status s_VT_Status
  163. (CONNECTOR connector,
  164.  EIO_Event dir)
  165. {
  166.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  167.     return xxx->sock ? SOCK_Status(xxx->sock, dir) : eIO_Success;
  168. }
  169. static EIO_Status s_VT_Wait
  170. (CONNECTOR       connector,
  171.  EIO_Event       event,
  172.  const STimeout* timeout)
  173. {
  174.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  175.     assert(event == eIO_Read || event == eIO_Write);
  176.     return xxx->sock ? SOCK_Wait(xxx->sock, event, timeout) : eIO_Closed;
  177. }
  178. static EIO_Status s_VT_Write
  179. (CONNECTOR       connector,
  180.  const void*     buf,
  181.  size_t          size,
  182.  size_t*         n_written,
  183.  const STimeout* timeout)
  184. {
  185.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  186.     if (!xxx->sock)
  187.         return eIO_Closed;
  188.     SOCK_SetTimeout(xxx->sock, eIO_Write, timeout);
  189.     return SOCK_Write(xxx->sock, buf, size, n_written, eIO_WritePlain);
  190. }
  191. static EIO_Status s_VT_Read
  192. (CONNECTOR       connector,
  193.  void*           buf,
  194.  size_t          size,
  195.  size_t*         n_read,
  196.  const STimeout* timeout)
  197. {
  198.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  199.     if (!xxx->sock)
  200.         return eIO_Closed;
  201.     SOCK_SetTimeout(xxx->sock, eIO_Read, timeout);
  202.     return SOCK_Read(xxx->sock, buf, size, n_read, eIO_ReadPlain);
  203. }
  204. static EIO_Status s_VT_Close
  205. (CONNECTOR       connector,
  206.  const STimeout* timeout)
  207. {
  208.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  209.     EIO_Status status = eIO_Success;
  210.     if (xxx->sock) {
  211.         SOCK_SetTimeout(xxx->sock, eIO_Write, timeout);
  212.         status = SOCK_Close(xxx->sock);
  213.         xxx->sock = 0;
  214.     }
  215.     return status;
  216. }
  217. #ifdef IMPLEMENTED__CONN_WaitAsync
  218. static EIO_Status s_VT_WaitAsync
  219. (void*                   connector,
  220.  FConnectorAsyncHandler  func,
  221.  SConnectorAsyncHandler* data)
  222. {
  223.     return eIO_NotSupported;
  224. }
  225. #endif
  226. static void s_Setup
  227. (SMetaConnector* meta,
  228.  CONNECTOR       connector)
  229. {
  230.     /* initialize virtual table */
  231.     CONN_SET_METHOD(meta, get_type,   s_VT_GetType,   connector);
  232.     CONN_SET_METHOD(meta, descr,      s_VT_Descr,     connector);
  233.     CONN_SET_METHOD(meta, open,       s_VT_Open,      connector);
  234.     CONN_SET_METHOD(meta, wait,       s_VT_Wait,      connector);
  235.     CONN_SET_METHOD(meta, write,      s_VT_Write,     connector);
  236.     CONN_SET_METHOD(meta, flush,      0,              0);
  237.     CONN_SET_METHOD(meta, read,       s_VT_Read,      connector);
  238.     CONN_SET_METHOD(meta, status,     s_VT_Status,    connector);
  239.     CONN_SET_METHOD(meta, close,      s_VT_Close,     connector);
  240. #ifdef IMPLEMENTED__CONN_WaitAsync
  241.     CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
  242. #endif
  243.     meta->default_timeout = 0; /*infinite*/
  244. }
  245. static void s_Destroy
  246. (CONNECTOR connector)
  247. {
  248.     SSockConnector* xxx = (SSockConnector*) connector->handle;
  249.     if (xxx->host)
  250.         free(xxx->host);
  251.     if (xxx->init_data)
  252.         free(xxx->init_data);
  253.     free(xxx);
  254.     connector->handle = 0;
  255.     free(connector);
  256. }
  257. static CONNECTOR s_Init
  258. (SOCK           sock,
  259.  const char*    host,
  260.  unsigned short port,
  261.  unsigned int   max_try,
  262.  const void*    init_data,
  263.  size_t         init_size,
  264.  TSCC_Flags     flags)
  265. {
  266.     CONNECTOR       ccc = (SConnector    *) malloc(sizeof(SConnector    ));
  267.     SSockConnector* xxx = (SSockConnector*) malloc(sizeof(SSockConnector));
  268.     /* parameter check: either sock or host/port, not both */
  269.     assert((!sock && host && port) || (sock && !host && !port));
  270.     assert(!init_size || init_data);
  271.     /* initialize internal data structures */
  272.     xxx->sock        = sock;
  273.     xxx->host        = host ? strdup(host) : 0;
  274.     xxx->port        = port;
  275.     if (sock)
  276.         xxx->max_try = SOCK_IsServerSide(sock) ? 0 : max_try;
  277.     else
  278.         xxx->max_try = max_try ? max_try : 1;
  279.     xxx->flags       = flags;
  280.     xxx->init_size   = init_data ? init_size : 0;
  281.     if (xxx->init_size) {
  282.         xxx->init_data = malloc(init_size);
  283.         memcpy(xxx->init_data, init_data, xxx->init_size);
  284.     } else {
  285.         xxx->init_data = 0;
  286.     }
  287.     /* initialize connector data */
  288.     ccc->handle  = xxx;
  289.     ccc->next    = 0;
  290.     ccc->meta    = 0;
  291.     ccc->setup   = s_Setup;
  292.     ccc->destroy = s_Destroy;
  293.     return ccc;
  294. }
  295. /***********************************************************************
  296.  *  EXTERNAL -- the connector's "constructors"
  297.  ***********************************************************************/
  298. extern CONNECTOR SOCK_CreateConnector
  299. (const char*    host,
  300.  unsigned short port,
  301.  unsigned int   max_try)
  302. {
  303.     return s_Init(0, host, port, max_try, 0, 0, 0);
  304. }
  305. extern CONNECTOR SOCK_CreateConnectorEx
  306. (const char*    host,
  307.  unsigned short port,
  308.  unsigned int   max_try,
  309.  const void*    init_data,
  310.  size_t         init_size,
  311.  TSCC_Flags     flags)
  312. {
  313.     return s_Init(0, host, port, max_try, init_data, init_size, flags);
  314. }
  315. extern CONNECTOR SOCK_CreateConnectorOnTop
  316. (SOCK         sock,
  317.  unsigned int max_try)
  318. {
  319.     return s_Init(sock, 0, 0, max_try, 0, 0, 0);
  320. }
  321. extern CONNECTOR SOCK_CreateConnectorOnTopEx
  322. (SOCK         sock,
  323.  unsigned int max_try,
  324.  TSCC_Flags   flags)
  325. {
  326.     return s_Init(sock, 0, 0, max_try, 0, 0, flags);
  327. }
  328. /*
  329.  * --------------------------------------------------------------------------
  330.  * $Log: ncbi_socket_connector.c,v $
  331.  * Revision 1000.0  2003/10/29 16:40:19  gouriano
  332.  * PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.19
  333.  *
  334.  * Revision 6.19  2003/08/25 14:42:14  lavr
  335.  * Employ new k..Timeout constants  --  log modification only
  336.  *
  337.  * Revision 6.18  2003/05/31 05:15:45  lavr
  338.  * Add ARGSUSED where args are meant to be unused, remove Flush
  339.  *
  340.  * Revision 6.17  2003/05/27 15:04:31  lavr
  341.  * +#include <stdio.h> (to define sprint's prototype on Mac)
  342.  *
  343.  * Revision 6.16  2003/05/14 03:54:23  lavr
  344.  * SOCKET_CreateConnectorOnTopEx(): number of parameters changed
  345.  * Implementation of CONN_Description() added
  346.  *
  347.  * Revision 6.15  2003/01/17 19:44:47  lavr
  348.  * Reduce dependencies
  349.  *
  350.  * Revision 6.14  2002/12/04 16:55:45  lavr
  351.  * Take advantage of SOCK_CreateEx()
  352.  *
  353.  * Revision 6.13  2002/10/28 15:46:21  lavr
  354.  * Use "ncbi_ansi_ext.h" privately
  355.  *
  356.  * Revision 6.12  2002/10/22 15:11:24  lavr
  357.  * Zero connector's handle to crash if revisited
  358.  *
  359.  * Revision 6.11  2002/08/12 15:12:46  lavr
  360.  * Use persistent SOCK_Write()
  361.  *
  362.  * Revision 6.10  2002/08/12 15:06:58  lavr
  363.  * Use persistent SOCK_Write()
  364.  *
  365.  * Revision 6.9  2002/08/07 16:37:45  lavr
  366.  * EIO_ReadMethod enums changed accordingly;
  367.  * eSCC_SetReadOnWrite processing added
  368.  *
  369.  * Revision 6.8  2002/04/26 16:37:05  lavr
  370.  * Added setting of default timeout in meta-connector's setup routine
  371.  * Remove all checks for kDefaultTimeout: now supplied good from CONN
  372.  *
  373.  * Revision 6.7  2001/12/04 15:55:07  lavr
  374.  * +SOCK_CreateConnectorOnTop(), +SOCK_CreateConnectorOnTopEx()
  375.  * Redesign of open-retry loop
  376.  *
  377.  * Revision 6.6  2001/04/24 21:30:27  lavr
  378.  * Added treatment of kDefaultTimeout
  379.  *
  380.  * Revision 6.5  2001/01/25 17:04:44  lavr
  381.  * Reversed:: DESTROY method calls free() to delete connector structure
  382.  *
  383.  * Revision 6.4  2001/01/23 23:09:47  lavr
  384.  * Flags added to 'Ex' constructor
  385.  *
  386.  * Revision 6.3  2001/01/11 16:38:18  lavr
  387.  * free(connector) removed from s_Destroy function
  388.  * (now always called from outside, in METACONN_Remove)
  389.  *
  390.  * Revision 6.2  2000/12/29 18:16:26  lavr
  391.  * Adapted for use of new connector structure.
  392.  *
  393.  * Revision 6.1  2000/04/07 20:05:38  vakatov
  394.  * Initial revision
  395.  *
  396.  * ==========================================================================
  397.  */