EIO_Status CConn_FtpStream::Drain(const STimeout* timeout) { const STimeout* r_timeout = kInfiniteTimeout/*0*/; const STimeout* w_timeout = kInfiniteTimeout/*0*/; CONN conn = GetCONN(); char block[1024]; if (conn) { size_t n; r_timeout = CONN_GetTimeout(conn, eIO_Read); w_timeout = CONN_GetTimeout(conn, eIO_Write); _VERIFY(SetTimeout(eIO_Read, timeout) == eIO_Success); _VERIFY(SetTimeout(eIO_Write, timeout) == eIO_Success); // Cause any upload-in-progress to abort CONN_Read (conn, block, sizeof(block), &n, eIO_ReadPlain); // Cause any command-in-progress to abort CONN_Write(conn, "NOOP\n", 5, &n, eIO_WritePersist); } clear(); while (read(block, sizeof(block))) ; if (!conn) return eIO_Closed; EIO_Status status; do { size_t n; status = CONN_Read(conn, block, sizeof(block), &n, eIO_ReadPersist); } while (status == eIO_Success); _VERIFY(CONN_SetTimeout(conn, eIO_Read, r_timeout) == eIO_Success); _VERIFY(CONN_SetTimeout(conn, eIO_Write, w_timeout) == eIO_Success); clear(); return status == eIO_Closed ? eIO_Success : status; }
void CId2Reader::x_ConnectAtSlot(TConn conn) { if ( GetDebugLevel() >= eTraceOpen ) { CDebugPrinter s(conn, "CId2Reader"); s << "New connection to " << m_Connector.GetServiceName() << "..."; } CReaderServiceConnector::SConnInfo conn_info = m_Connector.Connect(); CConn_IOStream& stream = *conn_info.m_Stream; SetRandomFail(stream, conn); if ( stream.bad() ) { NCBI_THROW(CLoaderException, eConnectionFailed, "cannot open connection: "+x_ConnDescription(stream)); } if ( GetDebugLevel() >= eTraceOpen ) { CDebugPrinter s(conn, "CId2Reader"); s << "New connection: " << x_ConnDescription(stream); } try { x_InitConnection(stream, conn); } catch ( CException& exc ) { m_Connector.RememberIfBad(conn_info); NCBI_RETHROW(exc, CLoaderException, eConnectionFailed, "connection initialization failed: "+ x_ConnDescription(stream)); } SetRandomFail(stream, conn); if ( stream.bad() ) { NCBI_THROW(CLoaderException, eConnectionFailed, "connection initialization failed: "+ x_ConnDescription(stream)); } // successfully received reply, server is good, forget it conn_info.MarkAsGood(); STimeout tmout; m_Connector.SetTimeoutTo(&tmout); CONN_SetTimeout(stream.GetCONN(), eIO_ReadWrite, &tmout); tmout.sec = 0; tmout.usec = 1; // no wait on close CONN_SetTimeout(stream.GetCONN(), eIO_Close, &tmout); m_Connections[conn] = conn_info; }
void CConn_Streambuf::x_Init(const STimeout* timeout, size_t buf_size, CConn_IOStream::TConn_Flags flags, CT_CHAR_TYPE* ptr, size_t size) { _ASSERT(m_Status == eIO_Success); if (timeout != kDefaultTimeout) { _VERIFY(CONN_SetTimeout(m_Conn, eIO_Open, timeout) ==eIO_Success); _VERIFY(CONN_SetTimeout(m_Conn, eIO_ReadWrite, timeout) ==eIO_Success); _VERIFY(CONN_SetTimeout(m_Conn, eIO_Close, timeout) ==eIO_Success); } if (!(flags & (CConn_IOStream::fConn_ReadBuffered | CConn_IOStream::fConn_WriteBuffered))) { buf_size = 0; } if (buf_size) { m_WriteBuf = new CT_CHAR_TYPE[buf_size << ((flags & (CConn_IOStream::fConn_ReadBuffered | CConn_IOStream::fConn_WriteBuffered)) == (CConn_IOStream::fConn_ReadBuffered | CConn_IOStream::fConn_WriteBuffered) ? 1 : 0)]; if (flags & CConn_IOStream::fConn_ReadBuffered) m_BufSize = buf_size; if (!(flags & CConn_IOStream::fConn_WriteBuffered)) buf_size = 0; if (flags & CConn_IOStream::fConn_ReadBuffered) m_ReadBuf = m_WriteBuf + buf_size; } /* else see ctor */ if (buf_size) setp(m_WriteBuf, m_WriteBuf + buf_size); /* else setp(0, 0) */ if (ptr) setg(ptr, ptr, ptr + size); // Initial get area else setg(m_ReadBuf, m_ReadBuf, m_ReadBuf); // Empty get area SCONN_Callback cb; cb.func = x_OnClose; /* NCBI_FAKE_WARNING: WorkShop */ cb.data = this; CONN_SetCallback(m_Conn, eCONN_OnClose, &cb, &m_Cb); m_CbValid = true; }
EIO_Status CConn_IOStream::SetTimeout(EIO_Event direction, const STimeout* timeout) const { CONN conn = GET_CONN(m_CSb); return conn ? CONN_SetTimeout(conn, direction, timeout) : eIO_Closed; }
void CONN_TestConnector (CONNECTOR connector, const STimeout* timeout, FILE* data_file, TTestConnFlags flags) { EIO_Status status; SConnector dummy; CONN conn; memset(&dummy, 0, sizeof(dummy)); TEST_LOG(eIO_Success, "[CONN_TestConnector] Starting..."); /* Fool around with dummy connector / connection */ assert(CONN_Create(0, &conn) != eIO_Success && !conn); assert(CONN_Create(&dummy, &conn) != eIO_Success && !conn); dummy.setup = s_DummySetup; assert(CONN_Create(&dummy, &conn) == eIO_Success); assert(CONN_Flush (conn) != eIO_Success); assert(CONN_ReInit(conn, 0) == eIO_Success); assert(CONN_ReInit(conn, 0) != eIO_Success); assert(CONN_ReInit(conn, &dummy) == eIO_Success); assert(CONN_Flush (conn) != eIO_Success); assert(CONN_ReInit(conn, &dummy) == eIO_Success); assert(CONN_ReInit(conn, 0) == eIO_Success); assert(CONN_Close (conn) == eIO_Success); /* CREATE new connection on the base of the connector, set * TIMEOUTs, try to RECONNECT, WAIT for the connection is writable */ assert(CONN_Create(connector, &conn) == eIO_Success); assert(CONN_SetTimeout(conn, eIO_Open, timeout) == eIO_Success); assert(CONN_SetTimeout(conn, eIO_ReadWrite, timeout) == eIO_Success); assert(CONN_SetTimeout(conn, eIO_Close, timeout) == eIO_Success); assert(CONN_ReInit(conn, connector) == eIO_Success); status = CONN_Wait(conn, eIO_Write, timeout); if (status != eIO_Success) { TEST_LOG(status, "[CONN_TestConnector] CONN_Wait(write) failed"); assert(status == eIO_Timeout); } /* Run the specified TESTs */ if ( !flags ) { flags = fTC_Everything; } if (flags & fTC_SingleBouncePrint) { s_SingleBouncePrint(conn, data_file); } if (flags & fTC_MultiBouncePrint) { s_MultiBouncePrint(conn, data_file); } if (flags & fTC_SingleBounceCheck) { s_SingleBounceCheck(conn, timeout, data_file); } /* And CLOSE the connection... */ assert(CONN_Close(conn) == eIO_Success); TEST_LOG(eIO_Success, "[CONN_TestConnector] Completed"); }
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) return s_CreateSocketConnector(net_info, 0, 0); /* 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 (user_header && !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)) { /* Auxiliary HTTP connector first */ EIO_Status status = eIO_Success; CONNECTOR c; CONN conn; /* Clear connection info */ uuu->host = 0; uuu->port = 0; uuu->ticket = 0; net_info->max_try = 1; c = 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 (c && (status = CONN_Create(c, &conn)) == eIO_Success) { CONN_SetTimeout(conn, eIO_Open, timeout); CONN_SetTimeout(conn, eIO_ReadWrite, timeout); CONN_SetTimeout(conn, eIO_Close, timeout); CONN_Flush(conn); /* This also triggers parse header callback */ CONN_Close(conn); } else { const char* error = c ? IO_StatusStr(status) : 0; CORE_LOGF_X(4, eLOG_Error, ("[%s] Unable to create auxiliary HTTP %s%s%s", uuu->service, c ? "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*/); } SOCK_ntoa(uuu->host, net_info->host, sizeof(net_info->host)); net_info->port = uuu->port; return s_CreateSocketConnector(net_info, &uuu->ticket, uuu->ticket ? sizeof(uuu->ticket) : 0); } return HTTP_CreateConnectorEx(net_info, (uuu->params.flags & (fHCC_Flushable | fHCC_NoAutoRetry)) | fHCC_AutoReconnect, s_ParseHeader, s_AdjustNetInfo, uuu/*adj.data*/, 0/*cleanup.data*/); }
streamsize CConn_Streambuf::showmanyc(void) { static const STimeout kZeroTmo = {0, 0}; _ASSERT(gptr() >= egptr()); if (!m_Conn) return -1L; // flush output buffer, if tied up to it if (m_Tie) x_sync(); const STimeout* tmo; const STimeout* timeout = CONN_GetTimeout(m_Conn, eIO_Read); if (timeout == kDefaultTimeout) { // HACK * HACK * HACK tmo = ((SMetaConnector*) m_Conn)->default_timeout; } else tmo = timeout; size_t x_read; bool backup = false; if (m_BufSize > 1) { if (eback() < gptr()) { x_Buf = gptr()[-1]; backup = true; } if (!tmo) _VERIFY(CONN_SetTimeout(m_Conn, eIO_Read, &kZeroTmo)==eIO_Success); m_Status = CONN_Read(m_Conn, m_ReadBuf + 1, m_BufSize - 1, &x_read, eIO_ReadPlain); if (!tmo) _VERIFY(CONN_SetTimeout(m_Conn, eIO_Read, timeout) ==eIO_Success); _ASSERT(x_read > 0 || m_Status != eIO_Success); } else { m_Status = CONN_Wait(m_Conn, eIO_Read, tmo ? tmo : &kZeroTmo); x_read = 0; } if (!x_read) { switch (m_Status) { case eIO_Success: _ASSERT(m_BufSize <= 1); return 1L; // can read at least 1 byte case eIO_Timeout: if (!tmo || !(tmo->sec | tmo->usec)) break; /*FALLTHRU*/ case eIO_Closed: return -1L; // EOF default: break; } return 0; // no data available immediately } m_ReadBuf[0] = x_Buf; _ASSERT(m_BufSize > 1); setg(m_ReadBuf + !backup, m_ReadBuf + 1, m_ReadBuf + 1 + x_read); x_GPos += x_read; return x_read; }