Beispiel #1
0
EIO_Status Soaker(const string& url, const string& data,
                  const STimeout* read_tmo,
                  const STimeout* write_tmo)
{
    static const STimeout kZeroTimeout = { 0 };

    CConn_HttpStream http(url, fHTTP_AutoReconnect, write_tmo);
    http.SetTimeout(eIO_Close, read_tmo);
    http.SetTimeout(eIO_Read, read_tmo);
    http << data << flush;

    EIO_Status status = CONN_Wait(http.GetCONN(), eIO_Read, &kZeroTimeout);
    if (status != eIO_Success) {
        if (status != eIO_Timeout)
            return status;
        status = http.Status(eIO_Write);
        if (status != eIO_Success)
            return status;
    }

    CWStream null(new CNullWriter, 0, 0, CRWStreambuf::fOwnWriter);
    NcbiStreamCopy(null, http);

    status = http.Status();
    if (status != eIO_Success  &&  status != eIO_Closed)
        return status;
    status = http.Status(eIO_Read);
    if (status != eIO_Closed)
        return status;
    return eIO_Success;
}
Beispiel #2
0
NLM_EXTERN EIO_Status VecScreenWaitForReply (
  CONN conn
)

{
  time_t           currtime, starttime;
  time_t           max = 0;
  EIO_Status       status;
  STimeout         timeout;
#ifdef OS_MAC
  EventRecord      currEvent;
#endif

  if (conn == NULL) return eIO_Unknown;

#ifdef OS_MAC
  timeout.sec = 0;
  timeout.usec = 0;
#else
  timeout.sec = 100;
  timeout.usec = 0;
#endif

  starttime = GetSecs ();
  while ((status = CONN_Wait (conn, eIO_Read, &timeout)) == eIO_Timeout && max < 300) {
    currtime = GetSecs ();
    max = currtime - starttime;
#ifdef OS_MAC
    WaitNextEvent (0, &currEvent, 0, NULL);
#endif
  }

  return status;
}
Beispiel #3
0
NLM_EXTERN EIO_Status QUERY_SendQuery (
  CONN conn
)

{
  static const STimeout kPollTimeout = { 0 };
  EIO_Status            status;

  if (conn == NULL) return eIO_Closed;

  /* flush buffer, sending query, without waiting for response */
  status = CONN_Wait (conn, eIO_Read, &kPollTimeout);
  return status == eIO_Timeout ? eIO_Success : status;
}
Beispiel #4
0
NLM_EXTERN Nlm_Int4 QUERY_CheckQueue (
  QUEUE* queue
)
{
  static const STimeout kPollTimeout = { 0 };
  Nlm_Int4       count = 0;
  QueuePtr       curr;
  QueuePtr       next;
  QueuePtr PNTR  qptr;
  EIO_Status     status;

  qptr = (QueuePtr PNTR) queue;
  if (qptr == NULL || *qptr == NULL) return 0;

  curr = *qptr;

  while (curr != NULL) {
    next = curr->next;

    if (curr->conn != NULL && (! curr->protect)) {
      status = CONN_Wait (curr->conn, eIO_Read, &kPollTimeout);

      if (status == eIO_Success || status == eIO_Closed) {
        /* protect against reentrant calls if resultproc is GUI and processes timer */
        curr->protect = TRUE;
        if (curr->resultproc != NULL) {
          /* result could eventually be used to reconnect on timeout */
          curr->resultproc (curr->conn, curr->userdata, status);
        }
        if (curr->closeConn) {
          CONN_Close (curr->conn);
        }
        QUERY_RemoveFromQueue (queue, curr->conn);
      } else {
        count++;
      }
    }

    curr = next;
  }

  return count;
}
Beispiel #5
0
EIO_Status CConnTest::ExtraCheckOnFailure(void)
{
    static const STimeout kTimeout   = { 5,      0 };
    static const STimeout kTimeSlice = { 0, 100000 };
    static const struct {
        const char*  host;
        const char* vhost;
    } kTests[] = {
        // 0. NCBI default
        { "",                           0                      }, // NCBI
        // 1. External server(s)
        { "www.google.com",             0                      },
        //    NB: Google's public DNS (also @8.8.8.8), responds at :80 as well
        { "8.8.4.4",                    "www.google.com"       },
        // 2. NCBI servers, explicitly
        { "www.be-md.ncbi.nlm.nih.gov", "www.ncbi.nlm.nih.gov" }, // NCBI main
        { "www.st-va.ncbi.nlm.nih.gov", "www.ncbi.nlm.nih.gov" }, // NCBI colo
        { "130.14.29.110",              "www.ncbi.nlm.nih.gov" }, // NCBI main
        { "165.112.7.20",               "www.ncbi.nlm.nih.gov" }  // NCBI colo
    };

    m_CheckPoint.clear();
    PreCheck(eNone, 0/*main*/, "Failback HTTP access check");

    SConnNetInfo* net_info = ConnNetInfo_Create(0, eDebugPrintout_Data);
    if (!net_info) {
        PostCheck(eNone, 0/*main*/,
                  eIO_Unknown, "Cannot create network info structure");
        return eIO_Unknown;
    }

    net_info->req_method = eReqMethod_Head;
    net_info->timeout    = &kTimeout;
    net_info->max_try    = 0;
    m_Timeout = 0;

    CDeadline deadline(kTimeout.sec, kTimeout.usec * 1000);
    time_t           sec;
    unsigned int nanosec;
    deadline.GetExpirationTime(&sec, &nanosec);
    ::sprintf(net_info->path, "/NcbiTest%08lX%08lX",
              (unsigned long) sec, (unsigned long) nanosec);

    vector< AutoPtr<CConn_HttpStream> > http;
    for (size_t n = 0;  n < sizeof(kTests) / sizeof(kTests[0]);  ++n) {
        char user_header[80];
        _ASSERT(::strlen(kTests[n].host) < sizeof(net_info->host) - 1);
        if (kTests[n].host[0])
            ::strcpy(net_info->host, kTests[n].host);
        if (kTests[n].vhost) {
            _ASSERT(::strlen(kTests[n].vhost) + 6 < sizeof(user_header) - 1);
            ::sprintf(user_header, "Host: %s", kTests[n].vhost);
        } else
            *user_header = '\0';
        SAuxData* auxdata = new SAuxData(m_Canceled, 0);
        http.push_back(new CConn_HttpStream(net_info, user_header, s_AnyHeader,
                                            auxdata, s_Adjust, s_Cleanup));
        http.back()->SetCanceledCallback(m_Canceled);
    }

    EIO_Status status = eIO_Success;
    do {
        if (!http.size())
            break;
        ERASE_ITERATE(vector< AutoPtr<CConn_HttpStream> >, h, http) {
            CONN conn = (*h)->GetCONN();
            if (!conn) {
                VECTOR_ERASE(h, http);
                if (status == eIO_Success)
                    status  = eIO_Unknown;
                continue;
            }
            EIO_Status readst = CONN_Wait(conn, eIO_Read, &kTimeSlice);
            if (readst > eIO_Timeout) {
                if (readst == eIO_Interrupt) {
                    status  = eIO_Interrupt;
                    break;
                }
                if (status < readst  &&  (*h)->GetStatusCode() != 404)
                    status = readst;
                VECTOR_ERASE(h, http);
                continue;
            }
        }
    } while (status != eIO_Interrupt  &&  !deadline.IsExpired());

    if (status == eIO_Success  &&  http.size())
        status  = eIO_Timeout;

    PostCheck(eNone, 0/*main*/, status, kEmptyStr);

    return status;
}
Beispiel #6
0
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");
}
Beispiel #7
0
static void s_SingleBounceCheck
(CONN            conn,
 const STimeout* timeout,
 FILE*           data_file)
{
    static const char sym[] = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
    };
    EIO_Status status;
    char message[128];

#define TEST_N_LINES 200
#define TEST_BUF_SIZE (TEST_N_LINES * (TEST_N_LINES + 3) / 2)
    char  buf[TEST_BUF_SIZE];

    TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  Starting...");

    /* WRITE to the connection:  "0\n12\n345\n6789\n01234\n........"
     */
    {{
        size_t k = 0, j = 0;
        size_t i;
        for (i = 0;  k != sizeof(buf);  i++) {
            /* prepare output data */
            size_t n_write, n_written;
            for (n_write = 0;  n_write < i;  n_write++, k++) {
                assert(k < sizeof(buf));
                buf[n_write] = sym[j++ % sizeof(sym)];
            }
            assert(k < sizeof(buf));
            if ( n_write ) {
                buf[n_write++] = '\n';  k++;
            }
            buf[n_write] = '\0';

            do { /* persistently */
                /* WAIT... sometimes */
                if (n_write % 5 == 3) {
                    status = CONN_Wait(conn, eIO_Write, timeout);
                    if (status != eIO_Success) {
                        TEST_LOG(status,
                                 "[s_SingleBounceCheck]  CONN_Wait(write)"
                                 " failed, retrying...");
                        assert(status == eIO_Timeout);
                    }
                }

                /* WRITE */
                status = CONN_Write(conn, buf, n_write,
                                    &n_written, eIO_WritePersist);
                if (status != eIO_Success) {
                    TEST_LOG(status,
                             "[s_SingleBounceCheck]  CONN_Write(persistent)"
                             " failed, retrying...");
                    assert(n_written < n_write);
                    assert(status == eIO_Timeout);
                } else {
                    assert(n_written == n_write);
                }
            } while (status != eIO_Success);
        }
    }}

    /* READ the "bounced" data from the connection, the first TEST_BUF_SIZE
     * bytes must be:  "0\n12\n345\n6789\n01234\n........"
     */
    {{
        char* x_buf;
        size_t n_read, n_to_read;

        memset(buf, '\0', TEST_BUF_SIZE);

        /* PEEK until the 1st 1/3 of the "bounced" data is available */
        x_buf = buf;
        n_to_read = TEST_BUF_SIZE/3;

        do {
            TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  1/3 PEEK...");
            status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPeek);
            if (status != eIO_Success) {
                TEST_LOG(status,
                         "[s_SingleBounceCheck]  1/3 CONN_Read(peek)"
                         " failed, retrying...");
                assert(n_read < n_to_read);
                assert(status == eIO_Timeout);
            }
            if (n_read < n_to_read) {
                sprintf(message, "[s_SingleBounceCheck]  1/3 CONN_Read(peek)"
                        " %lu byte%s peeked out of %lu byte%s, continuing...",
                        (unsigned long) n_read,    &"s"[n_read    == 1],
                        (unsigned long) n_to_read, &"s"[n_to_read == 1]);
                TEST_LOG(status, message);
            }
        } while (n_read != n_to_read);

        /* READ 1st 1/3 of "bounced" data, compare it with the PEEKed data */
        TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  1/3 READ...");
        status = CONN_Read(conn, x_buf + n_to_read, n_to_read, &n_read,
                           eIO_ReadPlain);
        if (status != eIO_Success) {
            TEST_LOG(status,
                     "[s_SingleBounceCheck]  1/3 CONN_Read(plain) failed");
        }
        assert(status == eIO_Success);
        assert(n_read == n_to_read);
        assert(memcmp(x_buf, x_buf + n_to_read, n_to_read) == 0);
        memset(x_buf + n_to_read, '\0', n_to_read);

        /* WAIT on read */
        status = CONN_Wait(conn, eIO_Read, timeout);
        if (status != eIO_Success) {
            TEST_LOG(status,
                     "[s_SingleBounceCheck]  CONN_Wait(read) failed");
            assert(status == eIO_Timeout);
        }

        /* READ the 2nd 1/3 of "bounced" data */
        x_buf = buf + TEST_BUF_SIZE/3;
        n_to_read = TEST_BUF_SIZE/3;

        while ( n_to_read ) {
            TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  2/3 READ...");
            status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPlain);
            if (status != eIO_Success) {
                sprintf(message, "[s_SingleBounceCheck]  2/3 CONN_Read(plain)"
                        " %lu byte%s read out of %lu byte%s, retrying...",
                        (unsigned long) n_read,    &"s"[n_read    == 1],
                        (unsigned long) n_to_read, &"s"[n_to_read == 1]);
                TEST_LOG(status, message);
                assert(n_read < n_to_read);
                assert(status == eIO_Timeout);
            } else {
                assert(n_read <= n_to_read);
            }
            n_to_read -= n_read;
            x_buf     += n_read;
        }
        assert(status == eIO_Success);

        /* Persistently READ the 3rd 1/3 of "bounced" data */
        n_to_read = TEST_BUF_SIZE - (x_buf - buf);

        TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  3/3 READ...");
        status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPersist);
        if (status != eIO_Success) {
            sprintf(message, "[s_SingleBounceCheck]  3/3 CONN_Read(persistent)"
                    " %lu byte%s read",
                    (unsigned long) n_read, &"s"[n_read == 1]);
            TEST_LOG(status, message);
            assert(n_read < n_to_read);
            assert(0);
        } else {
            assert(n_read == n_to_read);
        }
    }}

    /* Check for the received "bounced" data is identical to the sent data
     */
    {{
        const char* x_buf = buf;
        size_t k = 0, j = 0;
        size_t i;
        for (i = 1;  k != sizeof(buf);  i++) {
            size_t n;
            for (n = 0;  n < i;  n++, k++) {
                if (k == sizeof(buf))
                    break;
                assert(*x_buf++ == sym[j++ % sizeof(sym)]);
            }
            assert(*x_buf++ == '\n');  k++;
        }
    }}

    /* Now when the "bounced" data is read and tested, READ an arbitrary extra
     * data sent in by the peer and print it out to LOG file
     */
    if ( data_file ) {
        fprintf(data_file, "\ns_SingleBounceCheck(BEGIN EXTRA DATA)\n");
        fflush(data_file);
        for (;;) {
            size_t n;

            TEST_LOG(eIO_Success,
                     "[s_SingleBounceCheck]  EXTRA READ...");
            status = CONN_Read(conn, buf, sizeof(buf), &n, eIO_ReadPersist);
            TEST_LOG(status,
                     "[s_SingleBounceCheck]  EXTRA CONN_Read(persistent)");
            if ( n ) {
                assert(fwrite(buf, n, 1, data_file) == 1);
                fflush(data_file);
            }
            if (status == eIO_Closed  ||  status == eIO_Timeout)
                break; /* okay */

            assert(status == eIO_Success);
        }
        fprintf(data_file, "\ns_SingleBounceCheck(END EXTRA DATA)\n\n");
        fflush(data_file);
    }

    TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  ...finished");
}
Beispiel #8
0
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*/;
}
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;
}