SIZE_TYPE CSocketAPI::StringToHostPort(const string& str, unsigned int* host, unsigned short* port) { const char* s = str.c_str(); const char* e = SOCK_StringToHostPort(s, host, port); return e ? (SIZE_TYPE)(e - s) : NPOS; }
const char* DBLB_GetServer(const char* lb_name, TDBLB_Flags flags, const SDBLB_Preference* preference, const char* const skip_servers[], SDBLB_ConnPoint* conn_point, char* server_name_buf, size_t server_name_buflen, EDBLB_Status* result) { static const char kPrefix[] = "DB_IP__"; size_t len, n, a_skip, n_skip; SConnNetInfo* net_info; int/*bool*/ failed; unsigned int x_host; unsigned short x_port; double x_pref; SSERV_InfoCPtr* skip; SSERV_Info* info; SDBLB_ConnPoint cp; EDBLB_Status x; const char* c; if (!result) result = &x; if (server_name_buf) { assert(server_name_buflen); server_name_buf[0] = '\0'; } if (!conn_point) conn_point = &cp; memset(conn_point, 0, sizeof(*conn_point)); if (!lb_name || !*lb_name) { *result = eDBLB_BadName; return 0/*failure*/; } *result = eDBLB_Success; if (strchr(lb_name, '.')) { cp.host = SOCK_gethostbyname(lb_name); if (cp.host == SOCK_GetLoopbackAddress()) cp.host = /*FIXME?*/SERV_LOCALHOST; } else cp.host = 0; skip = 0; n_skip = 0; a_skip = 0; net_info = 0; failed = 0/*false*/; if (skip_servers) { for (n = 0; !failed && skip_servers[n]; n++) { const char* server = skip_servers[n]; SSERV_Info* info; if (!(len = strlen(server))) { continue; } if (strncasecmp(server, kPrefix, sizeof(kPrefix)-1) == 0 && isdigit((unsigned char) server[sizeof(kPrefix)-1])) { c = strstr(server + sizeof(kPrefix)-1, "__"); if (c) { size_t i = (size_t)(c - server) - (sizeof(kPrefix)-1); char* temp = strdup(server + sizeof(kPrefix)-1); if (temp) { char* s = temp + i; *s++ = ':'; memmove(s, s + 1, strlen(s + 1) + 1); server = temp; while (++temp < s) { if (*temp == '_') *temp = '.'; } len -= sizeof(kPrefix); } } } if (SOCK_StringToHostPort(server, &x_host, &x_port) != server + len) { int/*bool*/ resolved = 0/*false*/; const SSERV_Info* temp; SERV_ITER iter; if (!net_info) net_info = ConnNetInfo_Create(lb_name); iter = SERV_Open(skip_servers[n], fSERV_Standalone | fSERV_Dns | fSERV_Promiscuous, 0, net_info); do { SSERV_Info* dns; temp = SERV_GetNextInfo(iter); if (temp) { x_host = temp->host; if (x_host && s_IsSkipHost(x_host, cp.host)) { failed = 1/*true*/; break; } x_port = temp->port; } else if (!resolved) { x_host = 0; x_port = 0; } else break; if ((dns = SERV_CreateDnsInfo(x_host)) != 0) { dns->port = x_port; s_AddSkip(&skip, &a_skip, &n_skip, x_host ? dns : SERV_CopyInfoEx(dns, skip_servers[n])); if (!x_host) free(dns); } resolved = 1/*true*/; } while (temp); SERV_Close(iter); info = 0; } else if (s_IsSkipHost(x_host, cp.host)) { failed = 1/*true*/; info = 0; } else if (server != skip_servers[n]) { info = SERV_CreateStandaloneInfo(x_host, x_port); } else if ((info = SERV_CreateDnsInfo(x_host)) != 0) info->port = x_port; if (server != skip_servers[n]) free((void*) server); if (info) s_AddSkip(&skip, &a_skip, &n_skip, info); } } if (!failed && !cp.host) { if (preference) { x_host = preference->host; x_port = preference->port; if ((x_pref = preference->pref) < 0.0) x_pref = 0.0; else if (x_pref >= 100.0) x_pref = -1.0; } else { x_host = 0; x_port = 0; x_pref = 0.0; } if (!net_info) net_info = ConnNetInfo_Create(lb_name); info = SERV_GetInfoP(lb_name, fSERV_ReverseDns | fSERV_Standalone, x_host, x_port, x_pref, net_info, skip, n_skip, 0/*not external*/, 0, 0, 0); /* NCBI_FAKE_WARNING: GCC */ if (!info && (flags & fDBLB_AllowFallbackToStandby)) { /*FIXME: eliminate second pass by fix in ordering in ncbi_lbsmd.c*/ info = SERV_GetInfoP(lb_name, fSERV_ReverseDns | fSERV_Standalone | fSERV_IncludeSuppressed, x_host, x_port, x_pref, net_info, skip, n_skip, 0/*not external*/, 0, 0, 0); /* NCBI_FAKE_WARNING: GCC */ } } else info = 0; if (!info) { if (!failed) { if (!cp.host) { if (n_skip && (x_host = SOCK_gethostbyname(lb_name)) != 0) { for (n = 0; n < n_skip; n++) { if (x_host == skip[n]->host) { failed = 1/*true*/; break; } } } if (!failed && skip_servers) { for (n = 0; (c = skip_servers[n]) != 0; n++) { if (strcasecmp(c, lb_name) == 0) { failed = 1/*true*/; break; } } } } else if (conn_point != &cp) { conn_point->host = cp.host; conn_point->time = NCBI_TIME_INFINITE; } } if (!failed && server_name_buf) strncpy0(server_name_buf, lb_name, server_name_buflen - 1); *result = eDBLB_NotFound; } else { if (info->type != fSERV_Dns) { char* s, buf[80]; strncpy0(buf, kPrefix, sizeof(buf) - 1); SOCK_HostPortToString(info->host, info->port, buf + sizeof(kPrefix) - 1, sizeof(buf) - sizeof(kPrefix)); len = strlen(buf); if ((s = strchr(buf, ':')) != 0) memmove(s + 1, s, strlen(s) + 1); for (n = 0; n < len; n++) { if (buf[n] == '.' || buf[n] == ':') buf[n] = '_'; } if (server_name_buf) strncpy0(server_name_buf, buf, server_name_buflen - 1); *result = eDBLB_NoDNSEntry; } else if (info->host) { c = SERV_NameOfInfo(info); assert(c); if (server_name_buf) strncpy0(server_name_buf, c, server_name_buflen - 1); } else { failed = 1/*true*/; *result = eDBLB_ServiceDown; } if (!failed) { conn_point->host = info->host; conn_point->port = info->port; conn_point->time = info->time; } free(info); } for (n = 0; n < n_skip; n++) free((void*) skip[n]); if (skip) free((void*) skip); if (net_info) ConnNetInfo_Destroy(net_info); return failed ? 0 : (server_name_buf ? server_name_buf : lb_name); }
SSERV_Info* SERV_ReadInfoEx(const char* info_str, const char* name) { /* 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 int host; /* network byte order */ unsigned short port; /* host (native) byte order */ SSERV_Info* info; if (!str || (*str && !isspace((unsigned char)(*str)))) return 0; /* NB: "str" guarantees there is non-NULL attr */ while (*str && isspace((unsigned char)(*str))) str++; if (!ispunct((unsigned char)(*str)) || *str == ':') { if (!(str = SOCK_StringToHostPort(str, &host, &port))) return 0; while (*str && isspace((unsigned char)(*str))) str++; } else { host = 0; port = 0; } /* read server-specific info according to the detected type */ info = s_GetAttrByType(type)->vtable.Read(&str, name ? strlen(name)+1 : 0); if (!info) 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((unsigned char)(*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 ? -100000.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_Flag) i; str += n; break; } } } if (*str && !isspace((unsigned char)(*str))) break; while (*str && isspace((unsigned char)(*str))) str++; } if (*str) { free(info); info = 0; } else if (name) { strcpy((char*) info + SERV_SizeOfInfo(info), name); if (info->type == fSERV_Dns) info->u.dns.name = 1/*true*/; } else if (info->type == fSERV_Dns) { info->u.dns.name = 0/*false*/; } return info; }