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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbi_server_info.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 16:39:27  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.53
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbi_server_info.c,v 1000.0 2003/10/29 16:39:27 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, Denis Vakatov
  35.  *
  36.  * File Description:
  37.  *   NCBI server meta-address info
  38.  *
  39.  */
  40. #include "ncbi_ansi_ext.h"
  41. #include "ncbi_server_infop.h"
  42. #include <ctype.h>
  43. #include <math.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #define MAX_IP_ADDR_LEN  16 /* sizeof("255.255.255.255") */
  47. /*****************************************************************************
  48.  *  Attributes for the different server types::  Interface
  49.  */
  50. /* Table of virtual functions
  51.  */
  52. typedef struct {
  53.     char*       (*Write )(size_t reserve, const USERV_Info* u);
  54.     SSERV_Info* (*Read  )(const char** str);
  55.     size_t      (*SizeOf)(const USERV_Info *u);
  56.     int/*bool*/ (*Equal )(const USERV_Info *u1, const USERV_Info *u2);
  57. } SSERV_Info_VTable;
  58. /* Attributes
  59.  */
  60. typedef struct {
  61.     ESERV_Type        type;
  62.     const char*       tag;
  63.     size_t            tag_len;
  64.     SSERV_Info_VTable vtable;
  65. } SSERV_Attr;
  66. static const char* k_FlagTag[] = {
  67.     "Regular",  /* fSERV_Regular */
  68.     "Blast"     /* fSERV_Blast   */
  69. };
  70. /* Any server is not local by default.
  71.  */
  72. static int/*bool*/ s_LocalServerDefault = 0/*false*/;
  73. int/*bool*/ SERV_SetLocalServerDefault(int/*bool*/ onoff)
  74. {
  75.     int/*bool*/ retval = s_LocalServerDefault;
  76.     s_LocalServerDefault = onoff ? 1/*true*/ : 0/*false*/;
  77.     return retval;
  78. }
  79. /* Attributes' lookup (by either type or tag)
  80.  */
  81. static const SSERV_Attr* s_GetAttrByType(ESERV_Type type);
  82. static const SSERV_Attr* s_GetAttrByTag(const char* tag);
  83. const char* SERV_TypeStr(ESERV_Type type)
  84. {
  85.     const SSERV_Attr* attr = s_GetAttrByType(type);
  86.     if (attr)
  87.         return attr->tag;
  88.     return "";
  89. }
  90. const char* SERV_ReadType(const char* str, ESERV_Type* type)
  91. {
  92.     const SSERV_Attr* attr = s_GetAttrByTag(str);
  93.     if (!attr)
  94.         return 0;
  95.     *type = attr->type;
  96.     return str + attr->tag_len; 
  97. }
  98. /*****************************************************************************
  99.  *  Generic methods based on the server info's virtual functions
  100.  */
  101. char* SERV_WriteInfo(const SSERV_Info* info)
  102. {
  103.     char c_t[MAX_CONTENT_TYPE_LEN];    
  104.     const SSERV_Attr* attr;
  105.     size_t reserve;
  106.     char* str;
  107.     if (info->type != fSERV_Dns &&
  108.         info->mime_t != SERV_MIME_TYPE_UNDEFINED &&
  109.         info->mime_s != SERV_MIME_SUBTYPE_UNDEFINED) {
  110.         char* p;
  111.         if (!MIME_ComposeContentTypeEx(info->mime_t, info->mime_s,
  112.                                        info->mime_e, c_t, sizeof(c_t)))
  113.             return 0;
  114.         assert(c_t[strlen(c_t) - 2] == 'r' && c_t[strlen(c_t) - 1] == 'n');
  115.         c_t[strlen(c_t) - 2] = 0;
  116.         p = strchr(c_t, ' ');
  117.         assert(p);
  118.         p++;
  119.         memmove(c_t, p, strlen(p) + 1);
  120.     } else
  121.         *c_t = 0;
  122.     attr = s_GetAttrByType(info->type);
  123.     reserve = attr->tag_len+1 + MAX_IP_ADDR_LEN + 1+5/*port*/ + 1+10/*flag*/ +
  124.         1+9/*coef*/ + 3+strlen(c_t)/*cont.type*/ + 1+5/*locl*/ + 1+5/*priv*/ +
  125.         1+7/*quorum*/ + 1+14/*rate*/ + 1+5/*sful*/ + 1+12/*time*/ + 1/*EOL*/;
  126.     /* write server-specific info */
  127.     if ((str = attr->vtable.Write(reserve, &info->u)) != 0) {
  128.         char* s = str;
  129.         size_t n;
  130.         memcpy(s, attr->tag, attr->tag_len);
  131.         s += attr->tag_len;
  132.         *s++ = ' ';
  133.         s += HostPortToString(info->host, info->port, s, reserve);
  134.         if ((n = strlen(str + reserve)) != 0) {
  135.             *s++ = ' ';
  136.             memmove(s, str + reserve, n + 1);
  137.             s = str + strlen(str);
  138.         }
  139.         assert(info->flag < (int)(sizeof(k_FlagTag)/sizeof(k_FlagTag[0])));
  140.         if (k_FlagTag[info->flag] && *k_FlagTag[info->flag])
  141.             s += sprintf(s, " %s", k_FlagTag[info->flag]);
  142.         s += sprintf(s, " B=%.2f", info->coef);
  143.         if (*c_t)
  144.             s += sprintf(s, " C=%s", c_t);
  145.         s += sprintf(s, " L=%s", info->locl & 0x0F ? "yes" : "no");
  146.         if (info->type != fSERV_Dns && (info->locl & 0xF0))
  147.             s += sprintf(s, " P=yes");
  148.         if (info->host && info->quorum) {
  149.             if (info->quorum == (unsigned short)(-1))
  150.                 s += sprintf(s, " Q=yes");
  151.             else
  152.                 s += sprintf(s, " Q=%hu", info->quorum);
  153.         }
  154.         s += sprintf(s," R=%.*f", fabs(info->rate) < 0.01 ? 3 : 2, info->rate);
  155.         if (!(info->type & fSERV_Http) && info->type != fSERV_Dns)
  156.             s += sprintf(s, " S=%s", info->sful ? "yes" : "no");
  157.         s += sprintf(s, " T=%lu", (unsigned long)info->time);
  158.     }
  159.     return str;
  160. }
  161. SSERV_Info* SERV_ReadInfo(const char* info_str)
  162. {
  163.     /* detect server type */
  164.     ESERV_Type  type;
  165.     const char* str = SERV_ReadType(info_str, &type);
  166.     int/*bool*/ coef, mime, locl, priv, quorum, rate, sful, time;
  167.     unsigned short port;                /* host (native) byte order */
  168.     unsigned int host;                  /* network byte order       */
  169.     SSERV_Info *info;
  170.     if (!str || (*str && !isspace((unsigned char)(*str))))
  171.         return 0;
  172.     while (*str && isspace((unsigned char)(*str)))
  173.         str++;
  174.     if (!(str = StringToHostPort(str, &host, &port)))
  175.         return 0;
  176.     while (*str && isspace((unsigned char)(*str)))
  177.         str++;
  178.     /* read server-specific info according to the detected type */
  179.     if (!(info = s_GetAttrByType(type)->vtable.Read(&str)))
  180.         return 0;
  181.     info->host = host;
  182.     if (port)
  183.         info->port = port;
  184.     coef = mime = locl = priv = quorum = rate = sful = time = 0;/*unassigned*/
  185.     /* continue reading server info: optional parts: ... */
  186.     while (*str && isspace((unsigned char)(*str)))
  187.         str++;
  188.     while (*str) {
  189.         if (*(str + 1) == '=') {
  190.             int            n;
  191.             double         d;
  192.             unsigned short h;
  193.             unsigned long  t;
  194.             char           s[4];
  195.             EMIME_Type     mime_t;
  196.             EMIME_SubType  mime_s;
  197.             EMIME_Encoding mime_e;
  198.             
  199.             switch (toupper(*str++)) {
  200.             case 'B':
  201.                 if (!coef && sscanf(str, "=%lf%n", &d, &n) >= 1) {
  202.                     if (d < -100.0)
  203.                         d = -100.0;
  204.                     else if (d < 0.0)
  205.                         d = (d < -0.1 ? d : -0.1);
  206.                     else if (d < 0.01)
  207.                         d = 0.0;
  208.                     else if (d > 1000.0)
  209.                         d = 1000.0;
  210.                     info->coef = d;
  211.                     str += n;
  212.                     coef = 1;
  213.                 }
  214.                 break;
  215.             case 'C':
  216.                 if (type == fSERV_Dns)
  217.                     break;
  218.                 if (!mime && MIME_ParseContentTypeEx(str + 1, &mime_t,
  219.                                                      &mime_s, &mime_e)) {
  220.                     info->mime_t = mime_t;
  221.                     info->mime_s = mime_s;
  222.                     info->mime_e = mime_e;
  223.                     mime = 1;
  224.                     while (*str && !isspace((unsigned char)(*str)))
  225.                         str++;
  226.                 }
  227.                 break;
  228.             case 'L':
  229.                 if (!locl && sscanf(str, "=%3s%n", s, &n) >= 1) {
  230.                     if (strcasecmp(s, "YES") == 0) {
  231.                         info->locl |=  0x01/*true in low nibble*/;
  232.                         str += n;
  233.                         locl = 1;
  234.                     } else if (strcasecmp(s, "NO") == 0) {
  235.                         info->locl &= ~0x0F/*false in low nibble*/;
  236.                         str += n;
  237.                         locl = 1;
  238.                     }
  239.                 }
  240.                 break;
  241.             case 'P':
  242.                 if (type == fSERV_Dns)
  243.                     break;
  244.                 if (!priv && sscanf(str, "=%3s%n", s, &n) >= 1) {
  245.                     if (strcasecmp(s, "YES") == 0) {
  246.                         info->locl |=  0x10;/*true in high nibble*/
  247.                         str += n;
  248.                         priv = 1;
  249.                     } else if (strcasecmp(s, "NO") == 0) {
  250.                         info->locl &= ~0xF0;/*false in high nibble*/
  251.                         str += n;
  252.                         priv = 1;
  253.                     }
  254.                 }
  255.                 break;
  256.             case 'Q':
  257.                 if (type == fSERV_Firewall || !info->host || quorum)
  258.                     break;
  259.                 if (sscanf(str,"=%3s%n",s,&n) >= 1 && strcasecmp(s, "YES")==0){
  260.                     info->quorum = (unsigned short)(-1);
  261.                     str += n;
  262.                     quorum = 1;
  263.                 } else if (sscanf(str, "=%hu%n", &h, &n) >= 1) {
  264.                     info->quorum = h;
  265.                     str += n;
  266.                     quorum = 1;
  267.                 }
  268.                 break;
  269.             case 'R':
  270.                 if (!rate && sscanf(str, "=%lf%n", &d, &n) >= 1) {
  271.                     if (fabs(d) < 0.001)
  272.                         d = 0.0;
  273.                     else if (fabs(d) > 100000.0)
  274.                         d = (d < 0.0 ? -1.0 : 1.0)*100000.0;
  275.                     info->rate = d;
  276.                     str += n;
  277.                     rate = 1;
  278.                 }
  279.                 break;
  280.             case 'S':
  281.                 if ((type & fSERV_Http) != 0)
  282.                     break;
  283.                 if (!sful && sscanf(str, "=%3s%n", s, &n) >= 1) {
  284.                     if (strcasecmp(s, "YES") == 0) {
  285.                         if (type == fSERV_Dns)
  286.                             break; /*check only here for compatibility*/
  287.                         info->sful = 1/*true */;
  288.                         str += n;
  289.                         sful = 1;
  290.                     } else if (strcasecmp(s, "NO") == 0) {
  291.                         info->sful = 0/* false */;
  292.                         str += n;
  293.                         sful = 1;
  294.                     }
  295.                 }
  296.                 break;
  297.             case 'T':
  298.                 if (!time && sscanf(str, "=%lu%n", &t, &n) >= 1) {
  299.                     info->time = (TNCBI_Time) t;
  300.                     str += n;
  301.                     time = 1;
  302.                 }
  303.                 break;
  304.             }
  305.         } else {
  306.             size_t i;
  307.             for (i = 0; i < sizeof(k_FlagTag)/sizeof(k_FlagTag[0]); i++) {
  308.                 size_t n = strlen(k_FlagTag[i]);
  309.                 if (strncasecmp(str, k_FlagTag[i], n) == 0) {
  310.                     info->flag = (ESERV_Flags) i;
  311.                     str += n;
  312.                     break;
  313.                 }
  314.             }
  315.         }
  316.         if (*str && !isspace((unsigned char)(*str)))
  317.             break;
  318.         while (*str && isspace((unsigned char)(*str)))
  319.             str++;
  320.     }
  321.     if (*str) {
  322.         free(info);
  323.         info = 0;
  324.     }
  325.     return info;
  326. }
  327. size_t SERV_SizeOfInfo(const SSERV_Info *info)
  328. {
  329.     return sizeof(*info) - sizeof(USERV_Info) +
  330.         s_GetAttrByType(info->type)->vtable.SizeOf(&info->u);
  331. }
  332. int/*bool*/ SERV_EqualInfo(const SSERV_Info *i1, const SSERV_Info *i2)
  333. {
  334.     if (i1->type != i2->type || i1->host != i2->host || i1->port != i2->port)
  335.         return 0;
  336.     return s_GetAttrByType(i1->type)->vtable.Equal(&i1->u, &i2->u);
  337. }
  338. /*****************************************************************************
  339.  *  NCBID::   constructor and virtual functions
  340.  */
  341. static char* s_Ncbid_Write(size_t reserve, const USERV_Info* u)
  342. {
  343.     const SSERV_NcbidInfo* info = &u->ncbid;
  344.     char* str = (char*) malloc(reserve + strlen(SERV_NCBID_ARGS(info))+3);
  345.     if (str)
  346.         sprintf(str + reserve, "%s",
  347.                 *SERV_NCBID_ARGS(info) ? SERV_NCBID_ARGS(info) : "''");
  348.     return str;
  349. }
  350. static SSERV_Info* s_Ncbid_Read(const char** str)
  351. {
  352.     SSERV_Info* info;
  353.     char        *args, *c;
  354.     if (!(args = strdup(*str)))
  355.         return 0;
  356.     for (c = args; *c; c++)
  357.         if (isspace((unsigned char)(*c))) {
  358.             *c++ = '';
  359.             while (*c && isspace((unsigned char)(*c)))
  360.                 c++;
  361.             break;
  362.         }
  363.     if ((info = SERV_CreateNcbidInfo(0, 80, args)) != 0)
  364.         *str += c - args;
  365.     free(args);
  366.     return info;
  367. }
  368. static size_t s_Ncbid_SizeOf(const USERV_Info* u)
  369. {
  370.     return sizeof(u->ncbid) + strlen(SERV_NCBID_ARGS(&u->ncbid))+1;
  371. }
  372. static int/*bool*/ s_Ncbid_Equal(const USERV_Info* u1, const USERV_Info* u2)
  373. {
  374.     return
  375.         strcmp(SERV_NCBID_ARGS(&u1->ncbid), SERV_NCBID_ARGS(&u2->ncbid)) == 0;
  376. }
  377. SSERV_Info* SERV_CreateNcbidInfo
  378. (unsigned int   host,
  379.  unsigned short port,
  380.  const char*    args)
  381. {
  382.     size_t args_len = args ? strlen(args) : 0;
  383.     SSERV_Info* info = (SSERV_Info*) malloc(sizeof(SSERV_Info) + args_len + 1);
  384.     if (info) {
  385.         info->type         = fSERV_Ncbid;
  386.         info->host         = host;
  387.         info->port         = port;
  388.         info->sful         = 0;
  389.         info->locl         = s_LocalServerDefault & 0x0F;
  390.         info->time         = 0;
  391.         info->coef         = 0.0;
  392.         info->rate         = 0.0;
  393.         info->mime_t       = SERV_MIME_TYPE_UNDEFINED;
  394.         info->mime_s       = SERV_MIME_SUBTYPE_UNDEFINED;
  395.         info->mime_e       = eENCOD_None;
  396.         info->flag         = SERV_DEFAULT_FLAG;
  397.         memset(&info->reserved, 0, sizeof(info->reserved));
  398.         info->quorum       = 0;
  399.         info->u.ncbid.args = (TNCBI_Size) sizeof(info->u.ncbid);
  400.         if (strcmp(args, "''") == 0) /* special case */
  401.             args = 0;
  402.         strcpy(SERV_NCBID_ARGS(&info->u.ncbid), args ? args : "");
  403.     }
  404.     return info;
  405. }
  406. /*****************************************************************************
  407.  *  STANDALONE::   constructor and virtual functions
  408.  */
  409. /*ARGSUSED*/
  410. static char* s_Standalone_Write(size_t reserve, const USERV_Info* u_info)
  411. {
  412.     char* str = (char*) malloc(reserve + 1);
  413.     if (str)
  414.         str[reserve] = '';
  415.     return str;
  416. }
  417. /*ARGSUSED*/
  418. static SSERV_Info* s_Standalone_Read(const char** str)
  419. {
  420.     return SERV_CreateStandaloneInfo(0, 0);
  421. }
  422. static size_t s_Standalone_SizeOf(const USERV_Info* u)
  423. {
  424.     return sizeof(u->standalone);
  425. }
  426. /*ARGSUSED*/
  427. static int/*bool*/ s_Standalone_Equal(const USERV_Info* u1,
  428.                                       const USERV_Info* u2)
  429. {
  430.     return 1;
  431. }
  432. SSERV_Info* SERV_CreateStandaloneInfo
  433. (unsigned int   host,
  434.  unsigned short port)
  435. {
  436.     SSERV_Info *info = (SSERV_Info*) malloc(sizeof(SSERV_Info));
  437.     if (info) {
  438.         info->type   = fSERV_Standalone;
  439.         info->host   = host;
  440.         info->port   = port;
  441.         info->sful   = 0;
  442.         info->locl   = s_LocalServerDefault & 0x0F;
  443.         info->time   = 0;
  444.         info->coef   = 0.0;
  445.         info->rate   = 0.0;
  446.         info->mime_t = SERV_MIME_TYPE_UNDEFINED;
  447.         info->mime_s = SERV_MIME_SUBTYPE_UNDEFINED;
  448.         info->mime_e = eENCOD_None;
  449.         info->flag   = SERV_DEFAULT_FLAG;
  450.         memset(&info->reserved, 0, sizeof(info->reserved));
  451.         info->quorum = 0;
  452.         memset(&info->u.standalone, 0, sizeof(info->u.standalone));
  453.     }
  454.     return info;
  455. }
  456. /*****************************************************************************
  457.  *  HTTP::   constructor and virtual functions
  458.  */
  459. static char* s_Http_Write(size_t reserve, const USERV_Info* u)
  460. {
  461.     const SSERV_HttpInfo* info = &u->http;
  462.     char* str = (char*) malloc(reserve + strlen(SERV_HTTP_PATH(info))+1 +
  463.                                strlen(SERV_HTTP_ARGS(info))+1);
  464.     if (str) {
  465.         int n = sprintf(str + reserve, "%s", SERV_HTTP_PATH(info));
  466.         
  467.         if (*SERV_HTTP_ARGS(info))
  468.             sprintf(str + reserve + n, "?%s", SERV_HTTP_ARGS(info));
  469.     }
  470.     return str;
  471. }
  472. static SSERV_Info* s_HttpAny_Read(ESERV_Type type, const char** str)
  473. {
  474.     SSERV_Info*    info;
  475.     char           *path, *args, *c;
  476.     if (!**str || !(path = strdup(*str)))
  477.         return 0;
  478.     for (c = path; *c; c++)
  479.         if (isspace((unsigned char)(*c))) {
  480.             *c++ = '';
  481.             while (*c && isspace((unsigned char)(*c)))
  482.                 c++;
  483.             break;
  484.         }
  485.     if ((args = strchr(path, '?')) != 0)
  486.         *args++ = '';
  487.     /* Sanity check: no parameter delimiter allowed within path */
  488.     if (!strchr(path, '&') &&
  489.         (info = SERV_CreateHttpInfo(type, 0, 80, path, args)) != 0)
  490.         *str += c - path;
  491.     else
  492.         info = 0;
  493.     free(path);
  494.     return info;
  495. }
  496. static SSERV_Info *s_HttpGet_Read(const char** str)
  497. {
  498.     return s_HttpAny_Read(fSERV_HttpGet, str);
  499. }
  500. static SSERV_Info *s_HttpPost_Read(const char** str)
  501. {
  502.     return s_HttpAny_Read(fSERV_HttpPost, str);
  503. }
  504. static SSERV_Info *s_Http_Read(const char** str)
  505. {
  506.     return s_HttpAny_Read(fSERV_Http, str);
  507. }
  508. static size_t s_Http_SizeOf(const USERV_Info* u)
  509. {
  510.     return sizeof(u->http) + strlen(SERV_HTTP_PATH(&u->http))+1 +
  511.         strlen(SERV_HTTP_ARGS(&u->http))+1;
  512. }
  513. static int/*bool*/ s_Http_Equal(const USERV_Info* u1, const USERV_Info* u2)
  514. {
  515.     return
  516.         strcmp(SERV_HTTP_PATH(&u1->http), SERV_HTTP_PATH(&u2->http)) == 0 &&
  517.         strcmp(SERV_HTTP_ARGS(&u1->http), SERV_HTTP_ARGS(&u2->http)) == 0;
  518. }
  519. SSERV_Info* SERV_CreateHttpInfo
  520. (ESERV_Type     type,
  521.  unsigned int   host,
  522.  unsigned short port,
  523.  const char*    path,
  524.  const char*    args)
  525. {
  526.     size_t add_len = (path ? strlen(path) : 0)+1 + (args ? strlen(args) : 0);
  527.     SSERV_Info* info;
  528.     if (type & ~fSERV_Http)
  529.         return 0;
  530.     if ((info = (SSERV_Info*) malloc(sizeof(SSERV_Info) + add_len+1)) != 0) {
  531.         info->type        = type;
  532.         info->host        = host;
  533.         info->port        = port;
  534.         info->sful        = 0;
  535.         info->locl        = s_LocalServerDefault & 0x0F;
  536.         info->time        = 0;
  537.         info->coef        = 0.0;
  538.         info->rate        = 0.0;
  539.         info->mime_t      = SERV_MIME_TYPE_UNDEFINED;
  540.         info->mime_s      = SERV_MIME_SUBTYPE_UNDEFINED;
  541.         info->mime_e      = eENCOD_None;
  542.         info->flag        = SERV_DEFAULT_FLAG;
  543.         memset(&info->reserved, 0, sizeof(info->reserved));
  544.         info->quorum      = 0;
  545.         info->u.http.path = (TNCBI_Size) sizeof(info->u.http);
  546.         info->u.http.args = (TNCBI_Size) (info->u.http.path +
  547.                                           strlen(path ? path : "")+1);
  548.         strcpy(SERV_HTTP_PATH(&info->u.http), path ? path : "");
  549.         strcpy(SERV_HTTP_ARGS(&info->u.http), args ? args : "");
  550.     }
  551.     return info;
  552. }
  553. /*****************************************************************************
  554.  *  FIREWALL::   constructor and virtual functions
  555.  */
  556. static char* s_Firewall_Write(size_t reserve, const USERV_Info* u_info)
  557. {
  558.     const char* name = SERV_TypeStr(u_info->firewall.type);
  559.     size_t namelen = strlen(name);
  560.     char* str = (char*) malloc(reserve + (namelen ? namelen + 1 : 0));
  561.     if (str)
  562.         strcpy(str + reserve, name);
  563.     return str;
  564. }
  565. static SSERV_Info* s_Firewall_Read(const char** str)
  566. {
  567.     ESERV_Type type;
  568.     const char* s;
  569.     if (!(s = SERV_ReadType(*str, &type)))
  570.         type = (ESERV_Type) fSERV_Any;
  571.     else
  572.         *str = s;
  573.     return SERV_CreateFirewallInfo(0, 0, type);
  574. }
  575. static size_t s_Firewall_SizeOf(const USERV_Info* u)
  576. {
  577.     return sizeof(u->firewall);
  578. }
  579. static int/*bool*/ s_Firewall_Equal(const USERV_Info* u1, const USERV_Info* u2)
  580. {
  581.     return u1->firewall.type == u2->firewall.type;
  582. }
  583. SSERV_Info* SERV_CreateFirewallInfo(unsigned int host, unsigned short port,
  584.                                     ESERV_Type type)
  585. {
  586.     SSERV_Info* info = (SSERV_Info*) malloc(sizeof(SSERV_Info));
  587.     if (info) {
  588.         info->type   = fSERV_Firewall;
  589.         info->host   = host;
  590.         info->port   = port;
  591.         info->sful   = 0;
  592.         info->locl   = s_LocalServerDefault & 0x0F;
  593.         info->time   = 0;
  594.         info->coef   = 0.0;
  595.         info->rate   = 0.0;
  596.         info->mime_t = SERV_MIME_TYPE_UNDEFINED;
  597.         info->mime_s = SERV_MIME_SUBTYPE_UNDEFINED;
  598.         info->mime_e = eENCOD_None;
  599.         info->flag   = SERV_DEFAULT_FLAG;
  600.         memset(&info->reserved, 0, sizeof(info->reserved));
  601.         info->quorum = 0;
  602.         info->u.firewall.type = type;
  603.     }
  604.     return info;
  605. }
  606. /*****************************************************************************
  607.  *  DNS::   constructor and virtual functions
  608.  */
  609. /*ARGSUSED*/
  610. static char* s_Dns_Write(size_t reserve, const USERV_Info* u_info)
  611. {
  612.     char* str = (char*) malloc(reserve + 1);
  613.     if (str)
  614.         str[reserve] = '';
  615.     return str;
  616. }
  617. /*ARGSUSED*/
  618. static SSERV_Info* s_Dns_Read(const char** str)
  619. {
  620.     return SERV_CreateDnsInfo(0);
  621. }
  622. static size_t s_Dns_SizeOf(const USERV_Info* u)
  623. {
  624.     return sizeof(u->dns);
  625. }
  626. /*ARGSUSED*/
  627. static int/*bool*/ s_Dns_Equal(const USERV_Info* u1, const USERV_Info* u2)
  628. {
  629.     return 1;
  630. }
  631. SSERV_Info* SERV_CreateDnsInfo(unsigned int host)
  632. {
  633.     SSERV_Info* info = (SSERV_Info*) malloc(sizeof(SSERV_Info));
  634.     if (info) {
  635.         info->type   = fSERV_Dns;
  636.         info->host   = host;
  637.         info->port   = 0;
  638.         info->sful   = 0;
  639.         info->locl   = s_LocalServerDefault & 0x0F;
  640.         info->time   = 0;
  641.         info->coef   = 0.0;
  642.         info->rate   = 0.0;
  643.         info->mime_t = SERV_MIME_TYPE_UNDEFINED;
  644.         info->mime_s = SERV_MIME_SUBTYPE_UNDEFINED;
  645.         info->mime_e = eENCOD_None;
  646.         info->flag   = SERV_DEFAULT_FLAG;
  647.         memset(&info->reserved, 0, sizeof(info->reserved));
  648.         info->quorum = 0;
  649.         memset(&info->u.dns.pad, 0, sizeof(info->u.dns.pad));
  650.     }
  651.     return info;
  652. }
  653. /*****************************************************************************
  654.  *  Attributes for the different server types::  Implementation
  655.  */
  656. static const char kNCBID     [] = "NCBID";
  657. static const char kSTANDALONE[] = "STANDALONE";
  658. static const char kHTTP_GET  [] = "HTTP_GET";
  659. static const char kHTTP_POST [] = "HTTP_POST";
  660. static const char kHTTP      [] = "HTTP";
  661. static const char kFIREWALL  [] = "FIREWALL";
  662. static const char kDNS       [] = "DNS";
  663. /* Note: be aware of "prefixness" of tag constants and order of
  664.  * their appearance in the table below, as comparison is done via
  665.  * "strncmp", which can result 'true' on a smaller fit fragment.
  666.  */
  667. static const SSERV_Attr s_SERV_Attr[] = {
  668.     { fSERV_Ncbid,
  669.       kNCBID,      sizeof(kNCBID) - 1,
  670.       {s_Ncbid_Write,       s_Ncbid_Read,
  671.        s_Ncbid_SizeOf,      s_Ncbid_Equal} },
  672.     { fSERV_Standalone,
  673.       kSTANDALONE, sizeof(kSTANDALONE) - 1,
  674.       {s_Standalone_Write,  s_Standalone_Read,
  675.        s_Standalone_SizeOf, s_Standalone_Equal} },
  676.     { fSERV_HttpGet,
  677.       kHTTP_GET,   sizeof(kHTTP_GET) - 1,
  678.       {s_Http_Write,        s_HttpGet_Read,
  679.        s_Http_SizeOf,       s_Http_Equal} },
  680.     { fSERV_HttpPost,
  681.       kHTTP_POST,  sizeof(kHTTP_POST) - 1,
  682.       {s_Http_Write,        s_HttpPost_Read,
  683.        s_Http_SizeOf,       s_Http_Equal} },
  684.     { fSERV_Http,
  685.       kHTTP,  sizeof(kHTTP) - 1,
  686.       {s_Http_Write,        s_Http_Read,
  687.        s_Http_SizeOf,       s_Http_Equal} },
  688.     { fSERV_Firewall,
  689.       kFIREWALL, sizeof(kFIREWALL) - 1,
  690.       {s_Firewall_Write,    s_Firewall_Read,
  691.        s_Firewall_SizeOf,   s_Firewall_Equal} },
  692.     { fSERV_Dns,
  693.       kDNS, sizeof(kDNS) - 1,
  694.       {s_Dns_Write,         s_Dns_Read,
  695.        s_Dns_SizeOf,        s_Dns_Equal} }
  696. };
  697. static const SSERV_Attr* s_GetAttrByType(ESERV_Type type)
  698. {
  699.     size_t i;
  700.     for (i = 0;  i < sizeof(s_SERV_Attr)/sizeof(s_SERV_Attr[0]);  i++) {
  701.         if (s_SERV_Attr[i].type == type)
  702.             return &s_SERV_Attr[i];
  703.     }
  704.     return 0;
  705. }
  706. static const SSERV_Attr* s_GetAttrByTag(const char* tag)
  707. {
  708.     if (tag) {
  709.         size_t i;
  710.         for (i = 0;  i < sizeof(s_SERV_Attr)/sizeof(s_SERV_Attr[0]);  i++) {
  711.             size_t len = s_SERV_Attr[i].tag_len;
  712.             if (strncmp(s_SERV_Attr[i].tag, tag, len) == 0)
  713.                 if (!tag[len] || /* avoid prefix-only match */
  714.                     !(isalnum((unsigned char) tag[len]) || tag[len] == '_'))
  715.                     return &s_SERV_Attr[i];
  716.         }
  717.     }
  718.     return 0;
  719. }
  720. /*
  721.  * --------------------------------------------------------------------------
  722.  * $Log: ncbi_server_info.c,v $
  723.  * Revision 1000.0  2003/10/29 16:39:27  gouriano
  724.  * PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.53
  725.  *
  726.  * Revision 6.53  2003/09/02 21:21:42  lavr
  727.  * Cleanup included headers
  728.  *
  729.  * Revision 6.52  2003/06/26 15:21:43  lavr
  730.  * Use server's default locality for fSERV_Dns infos
  731.  *
  732.  * Revision 6.51  2003/06/16 15:58:50  lavr
  733.  * Minor code format changes
  734.  *
  735.  * Revision 6.50  2003/05/31 05:16:28  lavr
  736.  * Add ARGSUSED where args are meant to be unused
  737.  *
  738.  * Revision 6.49  2003/04/25 15:21:05  lavr
  739.  * Explicit cast to avoid int->enum warning
  740.  *
  741.  * Revision 6.48  2003/03/13 19:08:26  lavr
  742.  * Allow missing type in Firewall server info specification
  743.  *
  744.  * Revision 6.47  2003/03/07 22:21:31  lavr
  745.  * Heed 'uninitted use' (false) warning by moving lines around
  746.  *
  747.  * Revision 6.46  2003/02/28 14:48:38  lavr
  748.  * String type match for size_t and int in few expressions
  749.  *
  750.  * Revision 6.45  2002/11/01 20:15:36  lavr
  751.  * Do not allow FIREWALL server specs to have Q flag
  752.  *
  753.  * Revision 6.44  2002/10/28 20:15:06  lavr
  754.  * -<connect/ncbi_server_info.h> ("ncbi_server_infop.h" should suffice)
  755.  *
  756.  * Revision 6.43  2002/10/28 15:46:21  lavr
  757.  * Use "ncbi_ansi_ext.h" privately
  758.  *
  759.  * Revision 6.42  2002/10/21 19:19:23  lavr
  760.  * 2(was:3)-digit precision if R is exactly 0.01
  761.  *
  762.  * Revision 6.41  2002/09/24 15:05:23  lavr
  763.  * Increase precision in SERV_Write() when R is small
  764.  *
  765.  * Revision 6.40  2002/09/17 15:39:33  lavr
  766.  * SSERV_Info::quorum moved past the reserved area
  767.  *
  768.  * Revision 6.39  2002/09/04 15:09:47  lavr
  769.  * Handle quorum field in SSERV_Info::, log moved to end
  770.  *
  771.  * Revision 6.38  2002/05/06 19:16:16  lavr
  772.  * +#include <stdio.h>
  773.  *
  774.  * Revision 6.37  2002/03/22 19:52:18  lavr
  775.  * Do not include <stdio.h>: included from ncbi_util.h or ncbi_priv.h
  776.  *
  777.  * Revision 6.36  2002/03/19 22:13:58  lavr
  778.  * Do not use home-made ANSI-extensions if the platform provides
  779.  *
  780.  * Revision 6.35  2002/03/11 21:59:00  lavr
  781.  * Support for changes in ncbi_server_info.h: DNS server type added as
  782.  * well as support for MIME encoding in server specifications
  783.  *
  784.  * Revision 6.34  2001/12/06 16:07:44  lavr
  785.  * More accurate string length estimation in SERV_WriteInfo()
  786.  *
  787.  * Revision 6.33  2001/11/25 22:12:00  lavr
  788.  * Replaced g_SERV_LocalServerDefault -> SERV_SetLocalServerDefault()
  789.  *
  790.  * Revision 6.32  2001/11/16 20:25:53  lavr
  791.  * +g_SERV_LocalServerDefault as a private global parameter
  792.  *
  793.  * Revision 6.31  2001/09/24 20:43:58  lavr
  794.  * TSERV_Flags reverted to 'int'; expilict cast added in comparison
  795.  *
  796.  * Revision 6.30  2001/09/10 21:17:10  lavr
  797.  * Support written for FIREWALL server type
  798.  *
  799.  * Revision 6.29  2001/06/19 19:12:01  lavr
  800.  * Type change: size_t -> TNCBI_Size; time_t -> TNCBI_Time
  801.  *
  802.  * Revision 6.28  2001/06/05 14:11:29  lavr
  803.  * SERV_MIME_UNDEFINED split into 2 (typed) constants:
  804.  * SERV_MIME_TYPE_UNDEFINED and SERV_MIME_SUBTYPE_UNDEFINED
  805.  *
  806.  * Revision 6.27  2001/06/04 17:01:06  lavr
  807.  * MIME type/subtype added to server descriptor
  808.  *
  809.  * Revision 6.26  2001/05/03 16:35:46  lavr
  810.  * Local bonus coefficient modified: meaning of negative value changed
  811.  *
  812.  * Revision 6.25  2001/04/24 21:38:21  lavr
  813.  * Additions to code to support new locality and bonus attributes of servers.
  814.  *
  815.  * Revision 6.24  2001/03/26 18:39:38  lavr
  816.  * Casting to (unsigned char) instead of (int) for ctype char.class macros
  817.  *
  818.  * Revision 6.23  2001/03/06 23:53:07  lavr
  819.  * SERV_ReadInfo can now consume either hostname or IP address
  820.  *
  821.  * Revision 6.22  2001/03/05 23:10:11  lavr
  822.  * SERV_WriteInfo & SERV_ReadInfo both take only one argument now
  823.  *
  824.  * Revision 6.21  2001/03/02 20:09:14  lavr
  825.  * Typo fixed
  826.  *
  827.  * Revision 6.20  2001/03/01 18:48:19  lavr
  828.  * NCBID allowed to have '' (special case) as an empty argument
  829.  *
  830.  * Revision 6.19  2001/01/03 22:34:44  lavr
  831.  * MAX_IP_ADDRESS_LEN -> MAX_IP_ADDR_LEN (as everywhere else)
  832.  *
  833.  * Revision 6.18  2000/12/29 17:59:38  lavr
  834.  * Reading and writing of SERV_Info now use SOCK_* utility functions
  835.  * SOCK_gethostaddr and SOCK_ntoa. More clean code for reading.
  836.  *
  837.  * Revision 6.17  2000/12/06 22:19:02  lavr
  838.  * Binary host addresses are now explicitly stated to be in network byte
  839.  * order, whereas binary port addresses now use native (host) representation
  840.  *
  841.  * Revision 6.16  2000/12/04 17:34:19  beloslyu
  842.  * the order of include files is important, especially on other Unixes!
  843.  * Look the man on inet_ntoa
  844.  *
  845.  * Revision 6.15  2000/10/20 17:13:30  lavr
  846.  * Service descriptor parse bug fixed
  847.  * Return empty string on unknown type (instead of abort) in 'SERV_TypeStr'
  848.  *
  849.  * Revision 6.14  2000/10/05 21:31:23  lavr
  850.  * Standalone connection marked "stateful" by default
  851.  *
  852.  * Revision 6.13  2000/06/05 20:21:20  lavr
  853.  * Eliminated gcc warning: "subscript has type `char'" in calls to
  854.  * classification macros (<ctype.h>) by explicit casting to unsigned chars
  855.  *
  856.  * Revision 6.12  2000/05/31 23:12:22  lavr
  857.  * First try to assemble things together to get working service mapper
  858.  *
  859.  * Revision 6.11  2000/05/24 16:45:15  lavr
  860.  * Introduced replacement for inet_ntoa: my_ntoa
  861.  *
  862.  * Revision 6.10  2000/05/23 21:05:33  lavr
  863.  * Memory leaks fixed (appeared after server-info structure rearrangement)
  864.  *
  865.  * Revision 6.9  2000/05/23 19:02:49  lavr
  866.  * Server-info now includes rate; verbal representation changed
  867.  *
  868.  * Revision 6.8  2000/05/22 16:53:11  lavr
  869.  * Rename service_info -> server_info everywhere (including
  870.  * file names) as the latter name is more relevant
  871.  *
  872.  * Revision 6.7  2000/05/18 14:12:43  lavr
  873.  * Cosmetic change
  874.  *
  875.  * Revision 6.6  2000/05/17 16:15:13  lavr
  876.  * NCBI_* (for ANSI ext) undone - now "ncbi_ansi_ext.h" does good prototyping
  877.  *
  878.  * Revision 6.5  2000/05/17 14:22:32  lavr
  879.  * Small cosmetic changes
  880.  *
  881.  * Revision 6.4  2000/05/16 15:09:02  lavr
  882.  * Added explicit type casting to get "very smart" compilers happy
  883.  *
  884.  * Revision 6.3  2000/05/15 19:06:09  lavr
  885.  * Use home-made ANSI extensions (NCBI_***)
  886.  *
  887.  * Revision 6.2  2000/05/12 21:42:59  lavr
  888.  * Cleaned up for the C++ compilation, etc.
  889.  *
  890.  * Revision 6.1  2000/05/12 18:36:26  lavr
  891.  * First working revision
  892.  *
  893.  * ==========================================================================
  894.  */