Beispiel #1
0
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);
}
Beispiel #2
0
/*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;
}
Beispiel #4
0
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;
}
Beispiel #6
0
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);
}
Beispiel #7
0
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;
}