Exemplo n.º 1
0
/* Try to fix connection parameters (called for an unconnected connector) */
static int/*bool*/ s_Adjust(SHttpConnector* uuu,
                            char**          retry,
                            EReadMode       read_mode)
{
    assert(!uuu->sock  &&  uuu->can_connect != eCC_None);

    /* we're here because something is going wrong */
    if (++uuu->failure_count >= uuu->net_info->max_try) {
        if (*retry)
            free(*retry);
        if (read_mode != eRM_DropUnread  &&  uuu->failure_count > 1) {
            CORE_LOGF_X(1, eLOG_Error,
                        ("[HTTP]  Too many failed attempts (%d),"
                         " giving up", uuu->failure_count));
        }
        uuu->can_connect = eCC_None;
        return 0/*failure*/;
    }

    /* adjust info before yet another connection attempt */
    if (*retry) {
        int fail/*parse*/;
        assert(**retry);
        if (**retry != '?') {
            if (uuu->net_info->req_method == eReqMethod_Get  ||  !uuu->w_len
                ||  (uuu->flags & fHCC_InsecureRedirect)) {
                int/*bool*/secure = uuu->net_info->scheme == eURL_Https ? 1 : 0;
                *uuu->net_info->args = '\0'/*arguments not inherited*/;
                fail = !ConnNetInfo_ParseURL(uuu->net_info, *retry);
                if (!fail  &&  secure  &&  uuu->net_info->scheme != eURL_Https
                    &&  !(uuu->flags & fHCC_InsecureRedirect)) {
                    fail = -1;
                }
            } else
                fail = -1;
        } else
            fail = 1;
        if (fail) {
            CORE_LOGF_X(2, eLOG_Error,
                        ("[HTTP]  %s to redirect to \"%s\"",
                         fail < 0 ? "Prohibited" : "Unable", *retry));
        }
        free(*retry);
        if (fail) {
            uuu->can_connect = eCC_None;
            return 0/*failure*/;
        }
    } else if (!uuu->adjust_net_info
               ||  uuu->adjust_net_info(uuu->net_info,
                                        uuu->adjust_data,
                                        uuu->failure_count) == 0) {
        if (read_mode != eRM_DropUnread  &&  uuu->failure_count > 1) {
            CORE_LOGF_X(3, eLOG_Error,
                        ("[HTTP]  Retry attempts (%d) exhausted,"
                         " giving up", uuu->failure_count));
        }
        uuu->can_connect = eCC_None;
        return 0/*failure*/;
    }

    ConnNetInfo_AdjustForHttpProxy(uuu->net_info);
    return 1/*success*/;
}
Exemplo n.º 2
0
extern
NCBI_XCONNECT_EXPORT  // FIXME: To remove once the API is fully official
CConn_IOStream* NcbiOpenURL(const string& url, size_t buf_size)
{
    {
        class CInPlaceConnIniter : protected CConnIniter
        {
        } conn_initer;
    }
    bool svc = x_IsIdentifier(url);

    AutoPtr<SConnNetInfo> net_info = ConnNetInfo_Create(svc ? url.c_str() : 0);

    if (svc)
        return new CConn_ServiceStream(url, fSERV_Any, net_info.get());

    unsigned int   host;
    unsigned short port;
    if (url.size() == CSocketAPI::StringToHostPort(url, &host, &port)  &&  port
        &&  net_info.get()) {
        net_info->req_method = eReqMethod_Connect;
    }

    if (ConnNetInfo_ParseURL(net_info.get(), url.c_str())) {
        _ASSERT(net_info);  // otherwise ConnNetInfo_ParseURL() would fail
        if (net_info->req_method == eReqMethod_Connect) {
            return new CConn_SocketStream(*net_info, 0, 0, fSOCK_LogDefault,
                                          net_info->timeout, buf_size);
        }
        switch (net_info->scheme) {
        case eURL_Https:
        case eURL_Http:
            return new CConn_HttpStream(net_info.get(), kEmptyStr, 0, 0, 0, 0,
                                        fHTTP_AutoReconnect,
                                        kDefaultTimeout, buf_size);
        case eURL_File:
            if (*net_info->host  ||  net_info->port)
                break; /*not supported*/
            _ASSERT(!*net_info->args);
            if (net_info->debug_printout) {
                net_info->req_method = eReqMethod_Any;
                net_info->firewall = 0;
                net_info->stateless = 0;
                net_info->lb_disable = 0;
                net_info->http_proxy_leak = 0;
                net_info->http_proxy_host[0] = '\0';
                net_info->http_proxy_port    =   0;
                net_info->http_proxy_user[0] = '\0';
                net_info->http_proxy_pass[0] = '\0';
                net_info->proxy_host[0]      = '\0';
                net_info->max_try = 0;
                net_info->timeout = kInfiniteTimeout;
                ConnNetInfo_SetUserHeader(net_info.get(), 0);
                if (net_info->http_referer) {
                    free((void*) net_info->http_referer);
                    net_info->http_referer = 0;
                }
                ConnNetInfo_Log(net_info.get(), eLOG_Note, CORE_GetLOG());
            }
            return new CConn_FileStream(net_info->path);
        case eURL_Ftp:
            if (!net_info->user[0]) {
                strcpy(net_info->user, "ftp");
                if (!net_info->pass[0])
                    strcpy(net_info->pass, "-none@");
            }
            return new CConn_FTPDownloadStream(*net_info, 0, 0, 0,
                                               net_info->timeout, buf_size);
        default:
            break;
        }
    }
    return 0;
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
static void TEST_ConnNetInfo(void)
{
    size_t n;
    char* str;
    char buf[80];
    SConnNetInfo* net_info;

    CORE_LOG(eLOG_Note, "ConnNetInfo test started");

    net_info = ConnNetInfo_Create(0);
    assert(net_info);

    assert(ConnNetInfo_ParseURL(net_info,
                                "ftp://*****:*****@host:8888/ro.t/p@th"
                                "?arg/arg:arg@arg:arg/arg"));
    assert(net_info->scheme                           == eURL_Ftp);
    assert(strcmp(net_info->user, "user")                    == 0);
    assert(strcmp(net_info->pass, "pass")                    == 0);
    assert(strcmp(net_info->host, "host")                    == 0);
    assert(       net_info->port                             == 8888);
    assert(strcmp(net_info->path, "/ro.t/p@th")              == 0);
    assert(strcmp(net_info->args, "arg/arg:arg@arg:arg/arg") == 0);

    assert(ConnNetInfo_ParseURL(net_info, "https://www/path"
                                "?arg:arg@arg#frag"));
    assert(       net_info->scheme            == eURL_Https);
    assert(      *net_info->user                       == 0);
    assert(      *net_info->pass                       == 0);
    assert(strcmp(net_info->host, "www")               == 0);
    assert(       net_info->port                       == 0);
    assert(strcmp(net_info->path, "/path")             == 0);
    assert(strcmp(net_info->args, "arg:arg@arg#frag")  == 0);

    assert(ConnNetInfo_ParseURL(net_info, "/path1?arg1#frag2"));
    assert(strcmp(net_info->args, "arg1#frag2")        == 0);

    assert(ConnNetInfo_ParseURL(net_info, "path0/0"));
    assert(strcmp(net_info->path, "/path0/0")          == 0);
    assert(strcmp(net_info->args, "#frag2")            == 0);

    assert(ConnNetInfo_ParseURL(net_info, "#frag3"));
    assert(strcmp(net_info->path, "/path0/0")          == 0);
    assert(strcmp(net_info->args, "#frag3")            == 0);

    assert(ConnNetInfo_ParseURL(net_info, "path2"));
    assert(strcmp(net_info->path, "/path0/path2")      == 0);
    assert(strcmp(net_info->args, "#frag3")            == 0);

    assert(ConnNetInfo_ParseURL(net_info, "/path3?arg3"));
    assert(strcmp(net_info->path, "/path3")            == 0);
    assert(strcmp(net_info->args, "arg3#frag3")        == 0);

    strcpy(net_info->user, "user");
    strcpy(net_info->pass, "pass");
    str = ConnNetInfo_URL(net_info);
    assert(str);
    assert(strcmp(str, "https://www/path3?arg3#frag3") == 0);
    free(str);

    assert(ConnNetInfo_ParseURL(net_info, "path4/path5?arg4#"));
    assert(strcmp(net_info->user, "user")              == 0);
    assert(strcmp(net_info->pass, "pass")              == 0);
    assert(strcmp(net_info->path, "/path4/path5")      == 0);
    assert(strcmp(net_info->args, "arg4")              == 0);

    assert(ConnNetInfo_ParseURL(net_info, "../path6"));
    assert(strcmp(net_info->path, "/path4/../path6")   == 0);
    assert(strcmp(net_info->args, "")                  == 0);

    ConnNetInfo_SetUserHeader(net_info, "");
    str = UTIL_PrintableString(net_info->http_user_header, 0, buf, 0);
    printf("HTTP User Header after set:\n%s%s%s\n",
           "\"" + !str, str ? buf : "NULL", "\"" + !str);
    assert(!net_info->http_user_header  &&  !str);

    ConnNetInfo_AppendUserHeader(net_info,
                                 "T0: V0\n"
                                 "T1:V1\r\n"
                                 "T2: V2\r\n"
                                 "T3: V3\n"
                                 "T4: V4\n"
                                 "T1: V6");
    str = UTIL_PrintableString(net_info->http_user_header, 0, buf, 0);
    if (str)
        *str = '\0';
    printf("HTTP User Header after append:\n%s%s%s\n",
           "\"" + !str, str ? buf : "NULL", "\"" + !str);
    assert(strcmp(net_info->http_user_header,
                  "T0: V0\n"
                  "T1:V1\r\n"
                  "T2: V2\r\n"
                  "T3: V3\n"
                  "T4: V4\n"
                  "T1: V6\r\n") == 0);

    ConnNetInfo_OverrideUserHeader(net_info,
                                   "T0\r\n"
                                   "T5: V5\n"
                                   "T1:    \t  \r\n"
                                   "T2:V2.1\r\n"
                                   "T3:V3\r\n"
                                   "T4: W4");
    str = UTIL_PrintableString(net_info->http_user_header, 0, buf, 0);
    if (str)
        *str = '\0';
    printf("HTTP User Header after override:\n%s%s%s\n",
           "\"" + !str, str ? buf : "NULL", "\"" + !str);
    assert(strcmp(net_info->http_user_header,
                  "T0: V0\n"
                  "T2:V2.1\r\n"
                  "T3:V3\n"
                  "T4: W4\r\n"
                  "T5: V5\r\n") == 0);

    ConnNetInfo_ExtendUserHeader(net_info,
                                 "T0: V0\n"
                                 "T1:V1\r\n"
                                 "T2:V2\n"
                                 "T3: T3:V3\n"
                                 "T4:\n"
                                 "T5");
    str = UTIL_PrintableString(net_info->http_user_header, 0, buf, 0);
    if (str)
        *str = '\0';
    printf("HTTP User Header after extend:\n%s%s%s\n",
           "\"" + !str, str ? buf : "NULL", "\"" + !str);
    assert(strcmp(net_info->http_user_header,
                  "T0: V0\n"
                  "T2:V2.1 V2\r\n"
                  "T3:V3 T3:V3\n"
                  "T4: W4\r\n"
                  "T5: V5\r\n"
                  "T1:V1\r\n") == 0);

    ConnNetInfo_SetUserHeader(net_info, 0);
    str = UTIL_PrintableString(net_info->http_user_header, 0, buf, 0);
    if (str)
        *str = '\0';
    printf("HTTP User Header after reset:\n%s%s%s\n",
           "\"" + !str, str ? buf : "NULL", "\"" + !str);
    assert(!net_info->http_user_header);

    for (n = 0; n < sizeof(net_info->args); n++)
        net_info->args[n] = "0123456789"[rand() % 10];

    strncpy0(net_info->args, "a=b&b=c&c=d", sizeof(net_info->args) - 1);
    printf("HTTP Arg: \"%s\"\n", net_info->args);

    ConnNetInfo_PrependArg(net_info, "d=e", 0);
    ConnNetInfo_PrependArg(net_info, "e", "f");
    printf("HTTP Arg after prepend: \"%s\"\n", net_info->args);

    ConnNetInfo_AppendArg(net_info, "f=g", 0);
    ConnNetInfo_AppendArg(net_info, "g", "h");
    printf("HTTP Arg after append: \"%s\"\n", net_info->args);

    ConnNetInfo_PreOverrideArg(net_info, "a=z&b", "y");
    ConnNetInfo_PreOverrideArg(net_info, "c", "x");
    printf("HTTP Arg after pre-override: \"%s\"\n", net_info->args);

    ConnNetInfo_PostOverrideArg(net_info, "d=w&e", "v");
    ConnNetInfo_PostOverrideArg(net_info, "f", "u");
    printf("HTTP Arg after post-override: \"%s\"\n", net_info->args);

    ConnNetInfo_DeleteArg(net_info, "g");
    ConnNetInfo_DeleteArg(net_info, "h=n");
    printf("HTTP Arg after delete: \"%s\"\n", net_info->args);

    ConnNetInfo_DeleteAllArgs(net_info, "a=b&p=q&f=d");
    printf("HTTP Arg after delete-all: \"%s\"\n", net_info->args);

    ConnNetInfo_LogEx(net_info, eLOG_Note, CORE_GetLOG());

    ConnNetInfo_Destroy(net_info);

    CORE_LOG(eLOG_Note, "ConnNetInfo test completed");
}