Example #1
0
CConn_SocketStream::CConn_SocketStream(const string&   host,
                                       unsigned short  port,
                                       const void*     data,
                                       size_t          size,
                                       TSOCK_Flags     flags,
                                       unsigned short  max_try,
                                       const STimeout* timeout,
                                       size_t          buf_size)
    : CConn_IOStream(TConn_Pair(SOCK_CreateConnectorEx(host.c_str(),
                                                       port,
                                                       max_try,
                                                       data,
                                                       size,
                                                       flags),
                                eIO_Unknown),
                     timeout, buf_size)
{
    return;
}
static CONNECTOR s_CreateSocketConnector(const SConnNetInfo* net_info,
                                         const void*         init_data,
                                         size_t              init_size)
{
    if (*net_info->http_proxy_host) {
        SOCK sock = 0;
        EIO_Status status = HTTP_CreateTunnelEx(net_info, fHCC_NoAutoRetry,
                                                init_data, init_size, &sock);
        if (status == eIO_Success) {
            assert(sock);
            return SOCK_CreateConnectorOnTop(sock, 1/*pass ownership*/);
        }
        assert(!sock);
    }
    return SOCK_CreateConnectorEx(net_info->firewall
                                  &&  *net_info->proxy_host
                                  ? net_info->proxy_host
                                  : net_info->host, net_info->port,
                                  1/*max.try*/, init_data, init_size,
                                  net_info->debug_printout
                                  == eDebugPrintout_Data
                                  ? fSOCK_LogOn : fSOCK_LogDefault);
}
static CONNECTOR s_Open(SServiceConnector* uuu,
                        const STimeout*    timeout,
                        const SSERV_Info*  info,
                        SConnNetInfo*      net_info,
                        int/*bool*/        second_try)
{
    int/*bool*/ but_last = 0/*false*/;
    const char* user_header; /* either "" or non-empty dynamic string */
    char*       iter_header;
    EReqMethod  req_method;

    if (info  &&  info->type != fSERV_Firewall) {
        /* Not a firewall/relay connection here */
        assert(!second_try);
        /* We know the connection point, let's try to use it! */
        if (info->type != fSERV_Standalone  ||  !net_info->stateless) {
            SOCK_ntoa(info->host, net_info->host, sizeof(net_info->host));
            net_info->port = info->port;
        }

        switch (info->type) {
        case fSERV_Ncbid:
            /* Connection directly to NCBID, add NCBID-specific tags */
            if (net_info->stateless) {
                /* Connection request with data */
                user_header = "Connection-Mode: STATELESS\r\n"; /*default*/
                req_method  = eReqMethod_Post;
            } else {
                /* We will be waiting for conn-info back */
                user_header = "Connection-Mode: STATEFUL\r\n";
                req_method  = eReqMethod_Get;
            }
            user_header = s_AdjustNetParams(uuu->service, net_info, req_method,
                                            NCBID_WEBPATH,
                                            SERV_NCBID_ARGS(&info->u.ncbid),
                                            0, user_header, info->mime_t,
                                            info->mime_s, info->mime_e, 0);
            break;
        case fSERV_Http:
        case fSERV_HttpGet:
        case fSERV_HttpPost:
            /* Connection directly to CGI */
            req_method  = info->type == fSERV_HttpGet
                ? eReqMethod_Get : (info->type == fSERV_HttpPost
                                    ? eReqMethod_Post : eReqMethod_Any);
            user_header = "Client-Mode: STATELESS_ONLY\r\n"; /*default*/
            user_header = s_AdjustNetParams(uuu->service, net_info, req_method,
                                            SERV_HTTP_PATH(&info->u.http),
                                            SERV_HTTP_ARGS(&info->u.http),
                                            0, user_header, info->mime_t,
                                            info->mime_s, info->mime_e, 0);
            break;
        case fSERV_Standalone:
            if (!net_info->stateless) {
                /* We create SOCKET connector here */
                return SOCK_CreateConnectorEx(net_info->host,
                                              net_info->port,
                                              1/*max.try*/,
                                              0/*init.data*/,
                                              0/*data.size*/,
                                              net_info->debug_printout ==
                                              eDebugPrintout_Data ?
                                              fSOCK_LogOn : fSOCK_LogDefault);
            }
            /* Otherwise, it will be a pass-thru connection via dispatcher */
            user_header = "Client-Mode: STATELESS_ONLY\r\n"; /*default*/
            user_header = s_AdjustNetParams(uuu->service, net_info,
                                            eReqMethod_Post, 0, 0,
                                            0, user_header, info->mime_t,
                                            info->mime_s, info->mime_e, 0);
            but_last = 1/*true*/;
            break;
        default:
            user_header = 0;
            break;
        }
    } else {
        EMIME_Type     mime_t;
        EMIME_SubType  mime_s;
        EMIME_Encoding mime_e;
        if (net_info->stateless  ||
            (info  &&  (info->u.firewall.type & fSERV_Http))) {
            if (info) {
                req_method = info->u.firewall.type == fSERV_HttpGet
                    ? eReqMethod_Get : (info->u.firewall.type == fSERV_HttpPost
                                        ? eReqMethod_Post : eReqMethod_Any);
                net_info->stateless = 1/*true*/;
            } else
                req_method = eReqMethod_Any;
        } else
            req_method = eReqMethod_Get;
        if (info) {
            mime_t = info->mime_t;
            mime_s = info->mime_s;
            mime_e = info->mime_e;
        } else {
            mime_t = eMIME_T_Undefined;
            mime_s = eMIME_Undefined;
            mime_e = eENCOD_None;
        }
        /* Firewall/relay connection to dispatcher, special tags */
        user_header = net_info->stateless
            ? "Client-Mode: STATELESS_ONLY\r\n" /*default*/
            : "Client-Mode: STATEFUL_CAPABLE\r\n";
        user_header = s_AdjustNetParams(uuu->service, net_info, req_method,
                                        0, 0, 0, user_header,
                                        mime_t, mime_s, mime_e, 0);
    }
    if (!user_header)
        return 0;

    if ((iter_header = SERV_Print(uuu->iter, net_info, but_last)) != 0) {
        size_t uh_len;
        if ((uh_len = strlen(user_header)) > 0) {
            char*  ih;
            size_t ih_len = strlen(iter_header);
            if ((ih = (char*) realloc(iter_header, ih_len + uh_len + 1)) != 0){
                strcpy(ih + ih_len, user_header);
                iter_header = ih;
            }
            free((char*) user_header);
        }
        user_header = iter_header;
    } else if (!*user_header)
        user_header = 0; /* special case of assignment of literal "" */

    if (uuu->user_header) {
        ConnNetInfo_DeleteUserHeader(net_info, uuu->user_header);
        free((void*) uuu->user_header);
    }
    uuu->user_header = user_header;
    if (!ConnNetInfo_OverrideUserHeader(net_info, user_header))
        return 0;

    if (!second_try) {
        ConnNetInfo_ExtendUserHeader
            (net_info, "User-Agent: NCBIServiceConnector/"
             DISP_PROTOCOL_VERSION
#ifdef NCBI_CXX_TOOLKIT
             " (C++ Toolkit)"
#else
             " (C Toolkit)"
#endif
             "\r\n");
    }

    if (!net_info->stateless  &&  (!info                         ||
                                   info->type == fSERV_Firewall  ||
                                   info->type == fSERV_Ncbid)) {
        /* HTTP connector is auxiliary only */
        EIO_Status status = eIO_Success;
        CONNECTOR conn;
        CONN c;

        /* Clear connection info */
        uuu->host = 0;
        uuu->port = 0;
        uuu->ticket = 0;
        net_info->max_try = 1;
        conn = HTTP_CreateConnectorEx(net_info,
                                      (uuu->params.flags & fHCC_Flushable)
                                      | fHCC_SureFlush/*flags*/,
                                      s_ParseHeader, 0/*adj.info*/,
                                      uuu/*adj.data*/, 0/*cleanup.data*/);
        /* Wait for connection info back (error-transparent by DISPD.CGI) */
        if (conn  &&  (status = CONN_Create(conn, &c)) == eIO_Success) {
            CONN_SetTimeout(c, eIO_Open,      timeout);
            CONN_SetTimeout(c, eIO_ReadWrite, timeout);
            CONN_SetTimeout(c, eIO_Close,     timeout);
            CONN_Flush(c);
            /* This also triggers parse header callback */
            CONN_Close(c);
        } else {
            const char* error = conn ? IO_StatusStr(status) : 0;
            CORE_LOGF_X(4, eLOG_Error,
                        ("[%s]  Unable to create auxiliary HTTP %s%s%s",
                         uuu->service, conn ? "connection" : "connector",
                         error  &&  *error ? ": " : "", error ? error : ""));
            assert(0);
        }
        if (!uuu->host)
            return 0/*failed, no connection info returned*/;
        if (uuu->host == (unsigned int)(-1)) {
            /* Firewall mode only in stateful mode, fallback requested */
            assert((!info  ||  info->type == fSERV_Firewall)  &&  !second_try);
            /* Try to use stateless mode instead */
            net_info->stateless = 1/*true*/;
            return s_Open(uuu, timeout, info, net_info, 1/*second try*/);
        }
        if (net_info->firewall  &&  *net_info->proxy_host)
            strcpy(net_info->host, net_info->proxy_host);
        else
            SOCK_ntoa(uuu->host, net_info->host, sizeof(net_info->host));
        net_info->port = uuu->port;
        /* Build and return target SOCKET connector */
        return SOCK_CreateConnectorEx(net_info->host,
                                      net_info->port,
                                      1/*max.try*/,
                                      &uuu->ticket,
                                      sizeof(uuu->ticket),
                                      net_info->debug_printout ==
                                      eDebugPrintout_Data ?
                                      fSOCK_LogOn : fSOCK_LogDefault);
    }
    return HTTP_CreateConnectorEx(net_info,
                                  (uuu->params.flags & fHCC_Flushable)
                                  | fHCC_AutoReconnect/*flags*/,
                                  s_ParseHeader, s_AdjustNetInfo,
                                  uuu/*adj.data*/, 0/*cleanup.data*/);
}