📄 ncbi_server_info.c
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbi_server_info.c,v $ * PRODUCTION Revision 1000.0 2003/10/29 16:39:27 gouriano * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.53 * PRODUCTION * =========================================================================== *//* $Id: ncbi_server_info.c,v 1000.0 2003/10/29 16:39:27 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anton Lavrentiev, Denis Vakatov * * File Description: * NCBI server meta-address info * */#include "ncbi_ansi_ext.h"#include "ncbi_server_infop.h"#include <ctype.h>#include <math.h>#include <stdio.h>#include <stdlib.h>#define MAX_IP_ADDR_LEN 16 /* sizeof("255.255.255.255") *//***************************************************************************** * Attributes for the different server types:: Interface *//* Table of virtual functions */typedef struct { char* (*Write )(size_t reserve, const USERV_Info* u); SSERV_Info* (*Read )(const char** str); size_t (*SizeOf)(const USERV_Info *u); int/*bool*/ (*Equal )(const USERV_Info *u1, const USERV_Info *u2);} SSERV_Info_VTable;/* Attributes */typedef struct { ESERV_Type type; const char* tag; size_t tag_len; SSERV_Info_VTable vtable;} SSERV_Attr;static const char* k_FlagTag[] = { "Regular", /* fSERV_Regular */ "Blast" /* fSERV_Blast */};/* Any server is not local by default. */static int/*bool*/ s_LocalServerDefault = 0/*false*/;int/*bool*/ SERV_SetLocalServerDefault(int/*bool*/ onoff){ int/*bool*/ retval = s_LocalServerDefault; s_LocalServerDefault = onoff ? 1/*true*/ : 0/*false*/; return retval;}/* Attributes' lookup (by either type or tag) */static const SSERV_Attr* s_GetAttrByType(ESERV_Type type);static const SSERV_Attr* s_GetAttrByTag(const char* tag);const char* SERV_TypeStr(ESERV_Type type){ const SSERV_Attr* attr = s_GetAttrByType(type); if (attr) return attr->tag; return "";}const char* SERV_ReadType(const char* str, ESERV_Type* type){ const SSERV_Attr* attr = s_GetAttrByTag(str); if (!attr) return 0; *type = attr->type; return str + attr->tag_len; }/***************************************************************************** * Generic methods based on the server info's virtual functions */char* SERV_WriteInfo(const SSERV_Info* info){ char c_t[MAX_CONTENT_TYPE_LEN]; const SSERV_Attr* attr; size_t reserve; char* str; if (info->type != fSERV_Dns && info->mime_t != SERV_MIME_TYPE_UNDEFINED && info->mime_s != SERV_MIME_SUBTYPE_UNDEFINED) { char* p; if (!MIME_ComposeContentTypeEx(info->mime_t, info->mime_s, info->mime_e, c_t, sizeof(c_t))) return 0; assert(c_t[strlen(c_t) - 2] == '\r' && c_t[strlen(c_t) - 1] == '\n'); c_t[strlen(c_t) - 2] = 0; p = strchr(c_t, ' '); assert(p); p++; memmove(c_t, p, strlen(p) + 1); } else *c_t = 0; attr = s_GetAttrByType(info->type); reserve = attr->tag_len+1 + MAX_IP_ADDR_LEN + 1+5/*port*/ + 1+10/*flag*/ + 1+9/*coef*/ + 3+strlen(c_t)/*cont.type*/ + 1+5/*locl*/ + 1+5/*priv*/ + 1+7/*quorum*/ + 1+14/*rate*/ + 1+5/*sful*/ + 1+12/*time*/ + 1/*EOL*/; /* write server-specific info */ if ((str = attr->vtable.Write(reserve, &info->u)) != 0) { char* s = str; size_t n; memcpy(s, attr->tag, attr->tag_len); s += attr->tag_len; *s++ = ' '; s += HostPortToString(info->host, info->port, s, reserve); if ((n = strlen(str + reserve)) != 0) { *s++ = ' '; memmove(s, str + reserve, n + 1); s = str + strlen(str); } assert(info->flag < (int)(sizeof(k_FlagTag)/sizeof(k_FlagTag[0]))); if (k_FlagTag[info->flag] && *k_FlagTag[info->flag]) s += sprintf(s, " %s", k_FlagTag[info->flag]); s += sprintf(s, " B=%.2f", info->coef); if (*c_t) s += sprintf(s, " C=%s", c_t); s += sprintf(s, " L=%s", info->locl & 0x0F ? "yes" : "no"); if (info->type != fSERV_Dns && (info->locl & 0xF0)) s += sprintf(s, " P=yes"); if (info->host && info->quorum) { if (info->quorum == (unsigned short)(-1)) s += sprintf(s, " Q=yes"); else s += sprintf(s, " Q=%hu", info->quorum); } s += sprintf(s," R=%.*f", fabs(info->rate) < 0.01 ? 3 : 2, info->rate); if (!(info->type & fSERV_Http) && info->type != fSERV_Dns) s += sprintf(s, " S=%s", info->sful ? "yes" : "no"); s += sprintf(s, " T=%lu", (unsigned long)info->time); } return str;}SSERV_Info* SERV_ReadInfo(const char* info_str){ /* detect server type */ ESERV_Type type; const char* str = SERV_ReadType(info_str, &type); int/*bool*/ coef, mime, locl, priv, quorum, rate, sful, time; unsigned short port; /* host (native) byte order */ unsigned int host; /* network byte order */ SSERV_Info *info; if (!str || (*str && !isspace((unsigned char)(*str)))) return 0; while (*str && isspace((unsigned char)(*str))) str++; if (!(str = StringToHostPort(str, &host, &port))) return 0; while (*str && isspace((unsigned char)(*str))) str++; /* read server-specific info according to the detected type */ if (!(info = s_GetAttrByType(type)->vtable.Read(&str))) return 0; info->host = host; if (port) info->port = port; coef = mime = locl = priv = quorum = rate = sful = time = 0;/*unassigned*/ /* continue reading server info: optional parts: ... */ while (*str && isspace((unsigned char)(*str))) str++; while (*str) { if (*(str + 1) == '=') { int n; double d; unsigned short h; unsigned long t; char s[4]; EMIME_Type mime_t; EMIME_SubType mime_s; EMIME_Encoding mime_e; switch (toupper(*str++)) { case 'B': if (!coef && sscanf(str, "=%lf%n", &d, &n) >= 1) { if (d < -100.0) d = -100.0; else if (d < 0.0) d = (d < -0.1 ? d : -0.1); else if (d < 0.01) d = 0.0; else if (d > 1000.0) d = 1000.0; info->coef = d; str += n; coef = 1; } break; case 'C': if (type == fSERV_Dns) break; if (!mime && MIME_ParseContentTypeEx(str + 1, &mime_t, &mime_s, &mime_e)) { info->mime_t = mime_t; info->mime_s = mime_s; info->mime_e = mime_e; mime = 1; while (*str && !isspace((unsigned char)(*str))) str++; } break; case 'L': if (!locl && sscanf(str, "=%3s%n", s, &n) >= 1) { if (strcasecmp(s, "YES") == 0) { info->locl |= 0x01/*true in low nibble*/; str += n; locl = 1; } else if (strcasecmp(s, "NO") == 0) { info->locl &= ~0x0F/*false in low nibble*/; str += n; locl = 1; } } break; case 'P': if (type == fSERV_Dns) break; if (!priv && sscanf(str, "=%3s%n", s, &n) >= 1) { if (strcasecmp(s, "YES") == 0) { info->locl |= 0x10;/*true in high nibble*/ str += n; priv = 1; } else if (strcasecmp(s, "NO") == 0) { info->locl &= ~0xF0;/*false in high nibble*/ str += n; priv = 1; } } break; case 'Q': if (type == fSERV_Firewall || !info->host || quorum) break; if (sscanf(str,"=%3s%n",s,&n) >= 1 && strcasecmp(s, "YES")==0){ info->quorum = (unsigned short)(-1); str += n; quorum = 1; } else if (sscanf(str, "=%hu%n", &h, &n) >= 1) { info->quorum = h; str += n; quorum = 1; } break; case 'R': if (!rate && sscanf(str, "=%lf%n", &d, &n) >= 1) { if (fabs(d) < 0.001) d = 0.0; else if (fabs(d) > 100000.0) d = (d < 0.0 ? -1.0 : 1.0)*100000.0; info->rate = d; str += n; rate = 1; } break; case 'S': if ((type & fSERV_Http) != 0) break; if (!sful && sscanf(str, "=%3s%n", s, &n) >= 1) { if (strcasecmp(s, "YES") == 0) { if (type == fSERV_Dns) break; /*check only here for compatibility*/ info->sful = 1/*true */; str += n; sful = 1; } else if (strcasecmp(s, "NO") == 0) { info->sful = 0/* false */; str += n; sful = 1; } } break; case 'T': if (!time && sscanf(str, "=%lu%n", &t, &n) >= 1) { info->time = (TNCBI_Time) t; str += n; time = 1; } break; } } else { size_t i; for (i = 0; i < sizeof(k_FlagTag)/sizeof(k_FlagTag[0]); i++) { size_t n = strlen(k_FlagTag[i]); if (strncasecmp(str, k_FlagTag[i], n) == 0) { info->flag = (ESERV_Flags) i; str += n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -