/*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; }
/*ARGSUSED*/ const SSERV_VTable* SERV_LOCAL_Open(SERV_ITER iter, SSERV_Info** info, HOST_INFO* u/*unused*/) { struct SLOCAL_Data* data; if (!iter->ismask && strpbrk(iter->name, "?*")) return 0/*failed to start unallowed wildcard search*/; if (!(data = (struct SLOCAL_Data*) calloc(1, sizeof(*data)))) return 0; iter->data = data; if (g_NCBI_ConnectRandomSeed == 0) { g_NCBI_ConnectRandomSeed = iter->time ^ NCBI_CONNECT_SRAND_ADDEND; srand(g_NCBI_ConnectRandomSeed); } if (!s_LoadServices(iter)) { s_Reset(iter); s_Close(iter); return 0; } if (data->n_cand > 1) qsort(data->cand, data->n_cand, sizeof(*data->cand), s_Sort); /* call GetNextInfo subsequently if info is actually needed */ if (info) *info = 0; return &s_op; }
static EIO_Status s_VT_Close(CONNECTOR connector, const STimeout* timeout) { SServiceConnector* uuu = (SServiceConnector*) connector->handle; EIO_Status status = uuu->meta.close ? uuu->meta.close(uuu->meta.c_close, timeout) : eIO_Success; s_Close(connector, timeout, 1/*close_dispatcher*/); return status; }
const SSERV_VTable* SERV_LBSMD_Open(SERV_ITER iter, SSERV_Info** info, HOST_INFO* host_info, int/*bool*/ no_dispd_follows) { static int s_Init = 0; SSERV_Info* tmp; /* Daemon is running if LBSM_LBSMD returns 1: mutex exists but read operation failed with errno == EAGAIN (the mutex is busy) */ if (LBSM_LBSMD(0) <= 0 || errno != EAGAIN) return 0; if (!s_Init) { CORE_LOCK_WRITE; if (!s_Init && atexit(s_Fini) == 0) s_Init = 1; CORE_UNLOCK; } if (g_NCBI_ConnectRandomSeed == 0) { g_NCBI_ConnectRandomSeed = iter->time ^ NCBI_CONNECT_SRAND_ADDEND; srand(g_NCBI_ConnectRandomSeed); } if (!no_dispd_follows) iter->data = iter; tmp = s_GetNextInfo(iter, host_info); if (iter->data == iter) iter->data = 0; if (!tmp) { s_Close(iter); return 0; } if (info) *info = tmp; else if (tmp) free(tmp); return &s_op; }
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; }
static EIO_Status s_VT_Close(CONNECTOR connector, const STimeout* timeout) { return s_Close(connector, timeout, 1/*close_dispatcher*/); }