/* Connect to the HTTP server, specified by uuu->net_info's "port:host". * Return eIO_Success only if socket connection has succeeded and uuu->sock * is non-zero. If unsuccessful, try to adjust uuu->net_info by s_Adjust(), * and then re-try the connection attempt. */ static EIO_Status s_Connect(SHttpConnector* uuu, EReadMode read_mode) { EIO_Status status; assert(!uuu->sock); if (uuu->can_connect == eCC_None) { CORE_LOG_X(5, eLOG_Error, "[HTTP] Connector no longer usable"); return eIO_Closed; } /* the re-try loop... */ for (;;) { int/*bool*/ reset_user_header = 0; char* http_user_header = 0; char* null = 0; TSOCK_Flags flags; uuu->w_len = BUF_Size(uuu->w_buf); if (uuu->net_info->http_user_header) http_user_header = strdup(uuu->net_info->http_user_header); if (!uuu->net_info->http_user_header == !http_user_header) { ConnNetInfo_ExtendUserHeader (uuu->net_info, "User-Agent: NCBIHttpConnector" #ifdef NCBI_CXX_TOOLKIT " (C++ Toolkit)" #else " (C Toolkit)" #endif "\r\n"); reset_user_header = 1; } if (uuu->net_info->debug_printout) ConnNetInfo_Log(uuu->net_info, CORE_GetLOG()); flags = (uuu->net_info->debug_printout == eDebugPrintout_Data ? fSOCK_LogOn : fSOCK_LogDefault); if (uuu->net_info->scheme == eURL_Https) flags |= fSOCK_Secure; if (!(uuu->flags & fHCC_NoUpread)) flags |= fSOCK_ReadOnWrite; /* connect & send HTTP header */ if ((status = URL_ConnectEx (uuu->net_info->host, uuu->net_info->port, uuu->net_info->path, uuu->net_info->args, uuu->net_info->req_method, uuu->w_len, uuu->o_timeout, uuu->w_timeout, uuu->net_info->http_user_header, (int/*bool*/)(uuu->flags & fHCC_UrlEncodeArgs), flags, &uuu->sock)) != eIO_Success) { uuu->sock = 0; } if (reset_user_header) { ConnNetInfo_SetUserHeader(uuu->net_info, 0); uuu->net_info->http_user_header = http_user_header; } if (uuu->sock) break/*success*/; /* connection failed, no socket was created */ if (!s_Adjust(uuu, &null, read_mode)) break/*closed*/; } return status; }
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; }
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); }
int main(int argc, const char* argv[]) { const char* service = argc > 1 && *argv[1] ? argv[1] : "bounce"; static char obuf[8192 + 2]; SConnNetInfo* net_info; CONNECTOR connector; EIO_Status status; char ibuf[1024]; CONN conn; size_t n; setlocale(LC_ALL, ""); g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND; srand(g_NCBI_ConnectRandomSeed); CORE_SetLOGFormatFlags(fLOG_None | fLOG_Level | fLOG_OmitNoteLevel | fLOG_DateTime); CORE_SetLOGFILE(stderr, 0/*false*/); net_info = ConnNetInfo_Create(service); ConnNetInfo_AppendArg(net_info, "testarg", "val"); ConnNetInfo_AppendArg(net_info, "service", "none"); ConnNetInfo_AppendArg(net_info, "platform", "none"); ConnNetInfo_AppendArg(net_info, "address", "2010"); ConnNetInfo_Log(net_info, eLOG_Note, CORE_GetLOG()); connector = SERVICE_CreateConnectorEx(service, fSERV_Any, net_info, 0); if (!connector) CORE_LOG(eLOG_Fatal, "Failed to create service connector"); if (CONN_Create(connector, &conn) != eIO_Success) CORE_LOG(eLOG_Fatal, "Failed to create connection"); if (argc > 2) { strncpy0(obuf, argv[2], sizeof(obuf) - 2); obuf[n = strlen(obuf)] = '\n'; obuf[++n] = '\0'; if (CONN_Write(conn, obuf, strlen(obuf), &n, eIO_WritePersist) != eIO_Success) { CONN_Close(conn); CORE_LOG(eLOG_Fatal, "Cannot write to connection"); } assert(n == strlen(obuf)); } else { for (n = 0; n < 10; n++) { size_t m; for (m = 0; m < sizeof(obuf) - 2; m++) obuf[m] = "0123456789\n"[rand() % 11]; obuf[m++] = '\n'; obuf[m] = '\0'; if (CONN_Write(conn, obuf, strlen(obuf), &m, eIO_WritePersist) != eIO_Success) { if (!n) { CONN_Close(conn); CORE_LOG(eLOG_Fatal, "Cannot write to connection"); } else break; } assert(m == strlen(obuf)); } } for (;;) { if (CONN_Wait(conn, eIO_Read, net_info->timeout) != eIO_Success) { CONN_Close(conn); CORE_LOG(eLOG_Fatal, "Failed to wait for reading"); } status = CONN_Read(conn, ibuf, sizeof(ibuf), &n, eIO_ReadPersist); if (n) { char* descr = CONN_Description(conn); CORE_DATAF(eLOG_Note, ibuf, n, ("%lu bytes read from service (%s%s%s):", (unsigned long) n, CONN_GetType(conn), descr ? ", " : "", descr ? descr : "")); if (descr) free(descr); } if (status != eIO_Success) { if (status != eIO_Closed) CORE_LOGF(n ? eLOG_Error : eLOG_Fatal, ("Read error: %s", IO_StatusStr(status))); break; } } ConnNetInfo_Destroy(net_info); CONN_Close(conn); #if 0 CORE_LOG(eLOG_Note, "Trying ID1 service"); net_info = ConnNetInfo_Create(service); connector = SERVICE_CreateConnectorEx("ID1", fSERV_Any, net_info); ConnNetInfo_Destroy(net_info); if (!connector) CORE_LOG(eLOG_Fatal, "Service ID1 not available"); if (CONN_Create(connector, &conn) != eIO_Success) CORE_LOG(eLOG_Fatal, "Failed to create connection"); if (CONN_Write(conn, "\xA4\x80\x02\x01\x02\x00", 7, &n, eIO_WritePersist) != eIO_Success) { CONN_Close(conn); CORE_LOG(eLOG_Fatal, "Cannot write to service ID1"); } assert(n == 7); if (CONN_Read(conn, ibuf, sizeof(ibuf), &n, eIO_ReadPlain) != eIO_Success){ CONN_Close(conn); CORE_LOG(eLOG_Fatal, "Cannot read from service ID1"); } CORE_LOGF(eLOG_Note, ("%d bytes read from service ID1", n)); CONN_Close(conn); #endif CORE_LOG(eLOG_Note, "TEST completed successfully"); CORE_SetLOG(0); return 0/*okay*/; }