static CConn_IOStream::TConn_Pair s_ServiceConnectorBuilder(const char* service, TSERV_Type types, const SConnNetInfo* net_info, const char* user_header, const SSERVICE_Extra* params, const STimeout* timeout) { AutoPtr<SConnNetInfo> x_net_info(net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(service)); if (!x_net_info.get()) { NCBI_THROW(CIO_Exception, eUnknown, "CConn_ServiceStream::CConn_ServiceStream(): " " Out of memory"); } if (user_header && *user_header) ConnNetInfo_OverrideUserHeader(x_net_info.get(), user_header); x_SetupUserAgent(x_net_info.get()); if (timeout != kDefaultTimeout) x_net_info->timeout = timeout; CONNECTOR c = SERVICE_CreateConnectorEx(service, types, x_net_info.get(), params); return CConn_IOStream::TConn_Pair(c, eIO_Unknown); }
/*ARGSUSED*/ const SSERV_VTable* SERV_DISPD_Open(SERV_ITER iter, const SConnNetInfo* net_info, SSERV_Info** info, HOST_INFO* u/*unused*/) { struct SDISPD_Data* data; if (!(data = (struct SDISPD_Data*) calloc(1, sizeof(*data)))) return 0; iter->data = data; assert(net_info); /*must be called with non-NULL*/ data->net_info = ConnNetInfo_Clone(net_info); if (!ConnNetInfo_SetupStandardArgs(data->net_info, iter->name)) { s_Close(iter); return 0; } if (g_NCBI_ConnectRandomSeed == 0) { g_NCBI_ConnectRandomSeed = iter->time ^ NCBI_CONNECT_SRAND_ADDEND; srand(g_NCBI_ConnectRandomSeed); } /* Reset request method to be GET ('cause no HTTP body is ever used) */ data->net_info->req_method = eReqMethod_Get; if (iter->stateless) data->net_info->stateless = 1/*true*/; if ((iter->types & fSERV_Firewall) && !data->net_info->firewall) data->net_info->firewall = eFWMode_Adaptive; ConnNetInfo_ExtendUserHeader(data->net_info, "User-Agent: NCBIServiceDispatcher/" HTTP_DISP_VERSION #ifdef NCBI_CXX_TOOLKIT " (CXX Toolkit)" #else " (C Toolkit)" #endif /*NCBI_CXX_TOOLKIT*/ "\r\n"); data->n_skip = iter->n_skip; iter->op = &s_op; /*SERV_Update() [from HTTP callback] expects*/ s_Resolve(iter); iter->op = 0; if (!data->n_cand && (data->fail || !(data->net_info->stateless && data->net_info->firewall))) { s_Reset(iter); s_Close(iter); return 0; } /* call GetNextInfo subsequently if info is actually needed */ if (info) *info = 0; return &s_op; }
extern CONNECTOR SERVICE_CreateConnectorEx (const char* service, TSERV_Type types, const SConnNetInfo* net_info, const SSERVICE_Extra* params) { char* x_service; CONNECTOR ccc; SServiceConnector* xxx; if (!service || !*service || !(x_service = SERV_ServiceName(service))) return 0; ccc = (SConnector*) malloc(sizeof(SConnector)); xxx = (SServiceConnector*) calloc(1, sizeof(*xxx) + strlen(service)); /* initialize connector structures */ ccc->handle = xxx; ccc->next = 0; ccc->meta = 0; ccc->setup = s_Setup; ccc->destroy = s_Destroy; xxx->types = types; xxx->net_info = (net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(service)); if (!ConnNetInfo_SetupStandardArgs(xxx->net_info, x_service)) { free(x_service); s_Destroy(ccc); return 0; } strcpy((char*) xxx->service, service); free(x_service); /* now get ready for first probe dispatching */ if (types & fSERV_Stateless) xxx->net_info->stateless = 1/*true*/; if (types & fSERV_Firewall) xxx->net_info->firewall = 1/*true*/; if (!s_OpenDispatcher(xxx)) { s_Destroy(ccc); return 0; } assert(xxx->iter); /* finally, store all callback parameters */ if (params) memcpy(&xxx->params, params, sizeof(xxx->params)); /* done */ return ccc; }
static CConn_IOStream::TConn_Pair s_FtpConnectorBuilder(const SConnNetInfo* net_info, TFTP_Flags flag, const SFTP_Callback* cmcb, const STimeout* timeout) { _ASSERT(net_info); if (timeout == kDefaultTimeout) timeout = net_info->timeout; const SConnNetInfo* x_net_info; if (timeout != net_info->timeout) { SConnNetInfo* xx_net_info = ConnNetInfo_Clone(net_info); if (xx_net_info) xx_net_info->timeout = timeout; x_net_info = xx_net_info; } else x_net_info = net_info; CONNECTOR c = FTP_CreateConnector(x_net_info, flag, cmcb); if (x_net_info != net_info) ConnNetInfo_Destroy((SConnNetInfo*) x_net_info); return CConn_IOStream::TConn_Pair(c, eIO_Unknown); }
static CONNECTOR s_CreateConnector (const SConnNetInfo* net_info, const char* user_header, THCC_Flags flags, FHttpParseHTTPHeader parse_http_hdr, FHttpAdjustNetInfo adjust_net_info, void* adjust_data, FHttpAdjustCleanup adjust_cleanup) { char value[32]; CONNECTOR ccc; SHttpConnector* uuu; SConnNetInfo* xxx; xxx = net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(0); if (!xxx) return 0; if ((xxx->scheme != eURL_Unspec && xxx->scheme != eURL_Https && xxx->scheme != eURL_Http) || !ConnNetInfo_AdjustForHttpProxy(xxx)) { ConnNetInfo_Destroy(xxx); return 0; } if (!(ccc = (SConnector *) malloc(sizeof(SConnector ))) || !(uuu = (SHttpConnector*) malloc(sizeof(SHttpConnector)))) { if (ccc) free(ccc); ConnNetInfo_Destroy(xxx); return 0; } if (user_header) ConnNetInfo_OverrideUserHeader(xxx, user_header); s_AddReferer(xxx); ConnNetInfo_GetValue(0, "HTTP_INSECURE_REDIRECT", value, sizeof(value),""); if (*value && (strcmp (value, "1") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "yes") == 0 || strcasecmp(value, "on") == 0)) { flags |= fHCC_InsecureRedirect; } /* initialize internal data structure */ uuu->net_info = xxx; uuu->parse_http_hdr = parse_http_hdr; uuu->adjust_net_info = adjust_net_info; uuu->adjust_cleanup = adjust_cleanup; uuu->adjust_data = adjust_data; uuu->flags = flags; uuu->reserved = 0; uuu->can_connect = eCC_Once; /* will be properly set at open*/ ConnNetInfo_GetValue(0, "HTTP_ERROR_HEADER_ONLY", value, sizeof(value),""); uuu->error_header = (*value && (strcmp (value, "1") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "yes") == 0 || strcasecmp(value, "on") == 0)); uuu->sock = 0; uuu->o_timeout = kDefaultTimeout; /* deliberately bad values -- */ uuu->w_timeout = kDefaultTimeout; /* must be reset prior to use */ uuu->http = 0; uuu->r_buf = 0; uuu->w_buf = 0; /* there are some unintialized fields left -- they are initted later */ /* initialize connector structure */ ccc->handle = uuu; ccc->next = 0; ccc->meta = 0; ccc->setup = s_Setup; ccc->destroy = s_Destroy; return ccc; }
static CConn_IOStream::TConn_Pair s_HttpConnectorBuilder(const SConnNetInfo* net_info, const char* url, const char* host, unsigned short port, const char* path, const char* args, const char* user_header, FHTTP_ParseHeader parse_header, void* user_data, FHTTP_Adjust adjust, FHTTP_Cleanup cleanup, THTTP_Flags flags, const STimeout* timeout) { size_t len; AutoPtr<SConnNetInfo> x_net_info(net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(0)); if (!x_net_info.get()) { NCBI_THROW(CIO_Exception, eUnknown, "CConn_HttpStream::CConn_HttpStream(): Out of memory"); } if (url && !ConnNetInfo_ParseURL(x_net_info.get(), url)) { NCBI_THROW(CIO_Exception, eInvalidArg, "CConn_HttpStream::CConn_HttpStream(): Bad URL"); } if (host) { if ((len = *host ? strlen(host) : 0) >= sizeof(x_net_info->host)) { NCBI_THROW(CIO_Exception, eInvalidArg, "CConn_HttpStream::CConn_HttpStream(): Host too long"); } memcpy(x_net_info->host, host, ++len); } if (port) x_net_info->port = port; if (path) { if ((len = *path ? strlen(path) : 0) >= sizeof(x_net_info->path)) { NCBI_THROW(CIO_Exception, eInvalidArg, "CConn_HttpStream::CConn_HttpStream(): Path too long"); } memcpy(x_net_info->path, path, ++len); } if (args) { if ((len = *args ? strlen(args) : 0) >= sizeof(x_net_info->args)) { NCBI_THROW(CIO_Exception, eInvalidArg, "CConn_HttpStream::CConn_HttpStream(): Args too long"); } memcpy(x_net_info->args, args, ++len); } if (user_header && *user_header) ConnNetInfo_OverrideUserHeader(x_net_info.get(), user_header); x_SetupUserAgent(x_net_info.get()); if (timeout != kDefaultTimeout) x_net_info->timeout = timeout; CONNECTOR c = HTTP_CreateConnectorEx(x_net_info.get(), flags, parse_header, user_data, adjust, cleanup); return CConn_IOStream::TConn_Pair(c, eIO_Unknown); }
static CConn_IOStream::TConn_Pair s_SocketConnectorBuilder(const SConnNetInfo* net_info, const STimeout* timeout, const void* data, size_t size, TSOCK_Flags flags) { EIO_Status status = eIO_Success; bool proxy = false; SOCK sock = 0; _ASSERT(net_info); if ((flags & (fSOCK_LogOn | fSOCK_LogDefault)) == fSOCK_LogDefault && net_info->debug_printout == eDebugPrintout_Data) { flags &= ~fSOCK_LogDefault; flags |= fSOCK_LogOn; } if (*net_info->http_proxy_host && net_info->http_proxy_port) { status = HTTP_CreateTunnel(net_info, fHTTP_NoAutoRetry, &sock); _ASSERT(!sock ^ !(status != eIO_Success)); if (status == eIO_Success && ((flags & ~(fSOCK_LogOn | fSOCK_LogDefault)) || size)) { SOCK s; status = SOCK_CreateOnTopEx(sock, 0, &s, data, size, flags); _ASSERT(!s ^ !(status != eIO_Success)); SOCK_Destroy(sock); sock = s; } proxy = true; } if (!sock && (!proxy || net_info->http_proxy_leak)) { const char* host = (net_info->firewall && *net_info->proxy_host ? net_info->proxy_host : net_info->host); if (timeout == kDefaultTimeout) timeout = net_info->timeout; if (!proxy && net_info->debug_printout) { SConnNetInfo* x_net_info = ConnNetInfo_Clone(net_info); if (x_net_info) { x_net_info->req_method = eReqMethod_Any; x_net_info->stateless = 0; x_net_info->lb_disable = 0; x_net_info->http_proxy_host[0] = '\0'; x_net_info->http_proxy_port = 0; x_net_info->http_proxy_user[0] = '\0'; x_net_info->http_proxy_pass[0] = '\0'; x_net_info->proxy_host[0] = '\0'; ConnNetInfo_SetUserHeader(x_net_info, 0); if (x_net_info->http_referer) { free((void*) x_net_info->http_referer); x_net_info->http_referer = 0; } x_net_info->timeout = timeout; } ConnNetInfo_Log(x_net_info, eLOG_Note, CORE_GetLOG()); ConnNetInfo_Destroy(x_net_info); } status = SOCK_CreateEx(host, net_info->port, timeout, &sock, data, size, flags); _ASSERT(!sock ^ !(status != eIO_Success)); } string hostport(net_info->host); hostport += ':'; hostport += NStr::UIntToString(net_info->port); CONNECTOR c = SOCK_CreateConnectorOnTopEx(sock, 1/*own*/, hostport.c_str()); if (!c) { SOCK_Abort(sock); SOCK_Close(sock); status = eIO_Unknown; } return CConn_IOStream::TConn_Pair(c, status); }
static EIO_Status s_VT_Open(CONNECTOR connector, const STimeout* timeout) { SServiceConnector* uuu = (SServiceConnector*) connector->handle; SMetaConnector* meta = connector->meta; EIO_Status status; for (;;) { const SSERV_Info* info; SConnNetInfo* net_info; CONNECTOR conn; int stateless; assert(!uuu->meta.list && !uuu->name && !uuu->descr); if (!uuu->iter && !s_OpenDispatcher(uuu)) { status = eIO_Closed; break; } if (uuu->net_info->firewall && strcasecmp(uuu->iter->name, "local")) info = 0; else if (!(info = s_GetNextInfo(uuu))) { status = eIO_Closed; break; } if (!(net_info = ConnNetInfo_Clone(uuu->net_info))) { status = eIO_Unknown; break; } net_info->scheme = eURL_Unspec; conn = s_Open(uuu, timeout, info, net_info, 0/*!second_try*/); if (conn) uuu->descr = ConnNetInfo_URL(net_info); stateless = net_info->stateless; ConnNetInfo_Destroy(net_info); if (!conn) { if (!info) { status = eIO_Closed; break; } continue; } /* Setup the new connector on a temporary meta-connector... */ memset(&uuu->meta, 0, sizeof(uuu->meta)); METACONN_Add(&uuu->meta, conn); /* ...then link it in using current connection's meta */ conn->meta = meta; conn->next = meta->list; meta->list = conn; if (!uuu->descr && uuu->meta.descr) CONN_SET_METHOD(meta, descr, uuu->meta.descr, uuu->meta.c_descr); CONN_SET_METHOD (meta, wait, uuu->meta.wait, uuu->meta.c_wait); CONN_SET_METHOD (meta, write, uuu->meta.write, uuu->meta.c_write); CONN_SET_METHOD (meta, flush, uuu->meta.flush, uuu->meta.c_flush); CONN_SET_METHOD (meta, read, uuu->meta.read, uuu->meta.c_read); CONN_SET_METHOD (meta, status,uuu->meta.status,uuu->meta.c_status); if (uuu->meta.get_type) { const char* type; if ((type = uuu->meta.get_type(uuu->meta.c_get_type)) != 0) { size_t slen = strlen(uuu->service); size_t tlen = strlen(type); char* name = (char*) malloc(slen + tlen + 2); if (name) { memcpy(name, uuu->service, slen); name[slen++] = '/'; memcpy(name + slen, type, tlen); tlen += slen; name[tlen] = '\0'; uuu->name = name; } } } status = uuu->meta.open ? uuu->meta.open(uuu->meta.c_open, timeout) : eIO_Success; if (status == eIO_Success) break; if (!stateless && (!info || info->type == fSERV_Firewall)) { static const char kFWLink[] = { "http://www.ncbi.nlm.nih.gov" "/IEB/ToolBox/NETWORK" "/dispatcher.html#Firewalling"}; CORE_LOGF_X(6, eLOG_Error, ("[%s] %s connection failed (%s) indicating possible " "firewall configuration problem; please consult <%s>", uuu->service, !info ? "Firewall" : "Stateful relay", IO_StatusStr(status), kFWLink)); } s_Close(connector, timeout, 0/*don't close dispatcher just as yet*/); } uuu->status = status; return status; }