Exemplo n.º 1
0
END_NCBI_SCOPE


int main(int argc, char* argv[])
{
    USING_NCBI_SCOPE;

    // Setup error posting
    SetDiagTrace(eDT_Enable);
    SetDiagPostLevel(eDiag_Trace);
    SetDiagPostAllFlags(SetDiagPostAllFlags(eDPF_Default)
                        | eDPF_All | eDPF_OmitInfoSev);
    UnsetDiagPostFlag(eDPF_Line);
    UnsetDiagPostFlag(eDPF_File);
    UnsetDiagPostFlag(eDPF_Location);
    UnsetDiagPostFlag(eDPF_LongFilename);
    SetDiagTraceAllFlags(SetDiagPostAllFlags(eDPF_Default));

    // Init the library explicitly (this sets up the log)
    CONNECT_Init(0);

    STimeout tmo = { 5, 0 };
    EIO_Status status = Soaker(argv[1], "Hello", &tmo, &tmo);
    cout << "Status = " << IO_StatusStr(status) << endl;

    return !(status == eIO_Success);
}
Exemplo n.º 2
0
NLM_EXTERN CONN QUERY_OpenServiceQueryEx (
  const char* service,
  const char* parameters,
  Nlm_Uint4   timeoutsec,
  const char* arguments
)
{
  CONN           conn;
  CONNECTOR      connector;
  SConnNetInfo*  net_info;
  size_t         n_written;
  EIO_Status     status;

  /* fill in connection info fields and create the connection */
  net_info = ConnNetInfo_Create (service);
  ASSERT ( net_info );

  /* let the user agent be set with a program name */
  x_SetupUserHeader (net_info,
                     NULL, eMIME_T_Unknown, eMIME_Unknown, eENCOD_None);

  if (timeoutsec == (Nlm_Uint4)(-1L)) {
    net_info->timeout  = kInfiniteTimeout;
  } else if ( timeoutsec ) {
    net_info->tmo.sec  = timeoutsec;
    net_info->tmo.usec = timeoutsec;
    net_info->timeout  = &net_info->tmo;
  }

  ConnNetInfo_PostOverrideArg (net_info, arguments, 0);

  connector = SERVICE_CreateConnectorEx (service, fSERV_Any, net_info, 0);

  ConnNetInfo_Destroy (net_info);

  if (connector == NULL) {
    ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed in SERVICE_CreateConnectorEx");
    conn = NULL;
  } else if ((status = CONN_Create (connector, &conn)) != eIO_Success) {
    ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed in CONN_Create:"
               " %s", IO_StatusStr (status));
    ASSERT (conn == NULL);
  } else if (StringDoesHaveText (parameters)) {
    status = CONN_Write (conn, parameters, StringLen (parameters),
                         &n_written, eIO_WritePersist);
    if (status != eIO_Success) {
      ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed to write service parameters in CONN_Write: %s", IO_StatusStr (status));
      CONN_Close (conn);
      conn = NULL;
    }
  }

  return conn;
}
Exemplo n.º 3
0
static void s_Resolve(SERV_ITER iter)
{
    struct SDISPD_Data* data = (struct SDISPD_Data*) iter->data;
    SConnNetInfo* net_info = data->net_info;
    EIO_Status status = eIO_Success;
    CONNECTOR c = 0;
    CONN conn;
    char* s;

    assert(!(data->eof | data->fail));
    assert(!!net_info->stateless == !!iter->stateless);
    /* Obtain additional header information */
    if ((!(s = SERV_Print(iter, 0, 0))
         ||  ConnNetInfo_OverrideUserHeader(net_info, s))
        &&
        ConnNetInfo_OverrideUserHeader(net_info,
                                       iter->ok_down  &&  iter->ok_suppressed
                                       ? "Dispatch-Mode: PROMISCUOUS\r\n"
                                       : iter->ok_down
                                       ? "Dispatch-Mode: OK_DOWN\r\n"
                                       : iter->ok_suppressed
                                       ? "Dispatch-Mode: OK_SUPPRESSED\r\n"
                                       : "Dispatch-Mode: INFORMATION_ONLY\r\n")
        &&
        ConnNetInfo_OverrideUserHeader(net_info, iter->reverse_dns
                                       ? "Client-Mode: REVERSE_DNS\r\n"
                                       : !net_info->stateless
                                       ? "Client-Mode: STATEFUL_CAPABLE\r\n"
                                       : "Client-Mode: STATELESS_ONLY\r\n")) {
        c = HTTP_CreateConnectorEx(net_info, fHTTP_Flushable, s_ParseHeader,
                                   iter/*data*/, s_Adjust, 0/*cleanup*/);
    }
    if (s) {
        ConnNetInfo_DeleteUserHeader(net_info, s);
        free(s);
    }
    if (c  &&  (status = CONN_Create(c, &conn)) == eIO_Success) {
        /* Send all the HTTP data... */
        CONN_Flush(conn);
        /* ...then trigger the header callback */
        CONN_Close(conn);
    } else {
        CORE_LOGF_X(5, eLOG_Error,
                    ("%s%s%sUnable to create auxiliary HTTP %s: %s",
                     &"["[!*iter->name], iter->name, *iter->name ? "]  " : "",
                     c              ? "connection" : "connector",
                     IO_StatusStr(c ? status       : eIO_Unknown)));
        if (c  &&  c->destroy)
            c->destroy(c);
        assert(0);
    }
}
Exemplo n.º 4
0
static void TEST_CORE_Io(void)
{
  /* EIO_Status, IO_StatusStr() */
  int x_status;
  for (x_status = 0;  x_status <= (int) eIO_Unknown;  x_status++) {
    switch ( (EIO_Status) x_status ) {
    case eIO_Success:
    case eIO_Timeout:
    case eIO_Closed:
    case eIO_Interrupt:
    case eIO_InvalidArg:
    case eIO_NotSupported:
    case eIO_Unknown:
      assert(IO_StatusStr((EIO_Status) x_status));
      printf("IO_StatusStr(status = %d): \"%s\"\n",
             x_status, IO_StatusStr((EIO_Status) x_status));
      break;
    default:
      assert(0);
    }
  }
}
Exemplo n.º 5
0
static void s_ReadSocket(CSocket& sock, void* buffer,
        size_t buffer_size, size_t* bytes_read)
{
    EIO_Status status;

    while ((status = sock.Read(buffer,
            buffer_size, bytes_read)) == eIO_Interrupt)
        /* no-op */;

    if (status != eIO_Success) {
        // eIO_Timeout, eIO_Closed, eIO_InvalidArg,
        // eIO_NotSupported, eIO_Unknown
        NCBI_THROW_FMT(CNetStorageException, eIOError,
                "I/O error while reading from NetStorage server " <<
                        sock.GetPeerAddress() << ". "
                "Socket status: " << IO_StatusStr(status) << '.');
    }
}
Exemplo n.º 6
0
static void s_WriteToSocket(CSocket& sock,
        const char* output_buffer, size_t output_buffer_size)
{
    size_t bytes_written;

    while (output_buffer_size > 0) {
        EIO_Status  status = sock.Write(output_buffer,
                output_buffer_size, &bytes_written);
        if (status != eIO_Success) {
            // Error writing to the socket.
            // Log what we can.
            string message_start;

            if (output_buffer_size > 32) {
                CTempString buffer_head(output_buffer, 32);
                message_start = NStr::PrintableString(buffer_head);
                message_start += " (TRUNCATED)";
            } else {
                CTempString buffer_head(output_buffer, output_buffer_size);
                message_start = NStr::PrintableString(buffer_head);
            }

            NCBI_THROW_FMT(CNetStorageException, eIOError,
                    "Error writing message to the NetStorage server " <<
                            sock.GetPeerAddress() << ". "
                    "Socket write error status: " <<
                            IO_StatusStr(status) << ". "
                    "Bytes written: " <<
                            NStr::NumericToString(bytes_written) << ". "
                    "Message begins with: " << message_start);
        }

        output_buffer += bytes_written;
        output_buffer_size -= bytes_written;
    }
}
Exemplo n.º 7
0
BEGIN_NCBI_SCOPE


string CConn_Streambuf::x_Message(const char* msg)
{
    const char* type = m_Conn ? CONN_GetType    (m_Conn) : 0;
    char*       text = m_Conn ? CONN_Description(m_Conn) : 0;
    string result("CConn_Streambuf::");
    result += msg;
    if (type  ||  text) {
        result += " (";
        result += type ? type : "UNDEF";
        if (text) {
            _ASSERT(*text);
            result += "; ";
            result += text;
            free(text);
        }
        result += ')';
    }
    result += ": ";
    result += IO_StatusStr(m_Status);
    return result;
}
Exemplo n.º 8
0
int main(int argc, const char* argv[])
{
    CONN        conn;
    CONNECTOR   connector;
    EIO_Status  status;
    const char* inp_file;

    /* cmd.-line args */
    if (argc != 2) {
        Usage(argv[0], "Must specify the input file name");
    }
    inp_file = argv[1];

    /* log and data log streams */
    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
                           fLOG_OmitNoteLevel | fLOG_DateTime);
    CORE_SetLOGFILE(stderr, 0/*false*/);

    /* run the test */
    fprintf(stderr,
            "Starting the FILE CONNECTOR test...\n"
            "Copy data from file \"%s\" to file \"%s\".\n\n",
            inp_file, OUT_FILE);

    /* create connector, and bind it to the connection */
    connector = FILE_CreateConnector(inp_file, OUT_FILE);
    if ( !connector ) {
        Usage(argv[0], "Failed to create FILE connector");
    }

    verify(CONN_Create(connector, &conn) == eIO_Success);
 
    /* pump the data from one file to another */
    for (;;) {
        char buf[100];
        size_t n_read, n_written;

        /* read */
        status = CONN_Read(conn, buf, sizeof(buf), &n_read, eIO_ReadPlain);
        if (status != eIO_Success) {
            fprintf(stderr, "CONN_Read() failed (status: %s)\n",
                    IO_StatusStr(status));
            break;
        }
        fprintf(stderr, "READ: %ld  bytes\n", (long) n_read);

        /* write */
        status = CONN_Write(conn, buf, n_read, &n_written, eIO_WritePersist);
        if (status != eIO_Success) {
            fprintf(stderr, "CONN_Write() failed (status: %s)\n",
                    IO_StatusStr(status));
            assert(0);
            break;
        }
        assert(n_written == n_read);
    }
    assert(status == eIO_Closed);
    
    /* cleanup, exit */
    verify(CONN_Close(conn) == eIO_Success);
    CORE_LOG(eLOG_Note, "TEST completed successfully");
    CORE_SetLOG(0);
    return 0;
}
Exemplo n.º 9
0
static void TEST__server_2(SOCK sock, LSOCK lsock)
{
    EIO_Status status;
    size_t     n_io, n_io_done;
    char       buf[TEST_BUFSIZE];
    STimeout   r_to, w_to, rc_to;
    size_t     i;

    CORE_LOG(eLOG_Note, "TEST__server_2(TS2)");

    r_to.sec   = 0;
    r_to.usec  = 0;
    w_to = r_to;

    rc_to.sec  = 30;
    rc_to.usec = 123456;

    /* goto */
 l_reconnect: /* reconnection loopback */
    SOCK_SetDataLogging(sock, eOn);

    status = SOCK_SetTimeout(sock, eIO_Read,  &r_to);
    assert(status == eIO_Success);
    status = SOCK_SetTimeout(sock, eIO_Write, &w_to);
    assert(status == eIO_Success);

    for (i = 0;  ;  i++) {
        char* x_buf;

        /* read data from socket */
        n_io = sizeof(buf);
        status = SOCK_Read(sock, buf, n_io, &n_io_done, eIO_ReadPlain);
        switch ( status ) {
        case eIO_Success:
            CORE_LOGF(eLOG_Note,
                      ("TS2::read:"
                       " [%lu], status=%7s, n_io=%5lu, n_io_done=%5lu",
                       (unsigned long)i, IO_StatusStr(status),
                       (unsigned long)n_io, (unsigned long)n_io_done));
            assert(n_io_done > 0);
            break;

        case eIO_Closed:
            CORE_LOG(eLOG_Note, "TS2::read: connection closed");
            assert(SOCK_Status(sock, eIO_Read) == eIO_Closed);
            /* close connection */
            status = SOCK_Close(sock);
            assert(status == eIO_Success  ||  status == eIO_Closed);
            /* reconnect */
            if ( !lsock )
                return;

            CORE_LOG(eLOG_Note, "TS2::reconnect");
            if ((status = LSOCK_Accept(lsock, &rc_to, &sock)) != eIO_Success)
                return;
            assert(SOCK_Status(sock, eIO_Read) == eIO_Success);
            /* !!! */
            goto l_reconnect;

        case eIO_Timeout:
            CORE_LOGF(eLOG_Note,
                      ("TS2::read:"
                       " [%lu] timeout expired: %5u sec, %6u usec",
                       (unsigned long)i, r_to.sec, r_to.usec));
            assert(n_io_done == 0);
            s_DoubleTimeout(&r_to);
            status = SOCK_SetTimeout(sock, eIO_Read, &r_to);
            assert(status == eIO_Success);
            assert(SOCK_Status(sock, eIO_Read) == eIO_Timeout);
            break;

        default:
            CORE_LOGF(eLOG_Fatal,
                      ("TS2::read: status = %d", (int) status));
        } /* switch */

        /* write(just the same) data back to client */
        n_io  = n_io_done;
        x_buf = buf;
        while ( n_io ) {
            status = SOCK_Write(sock, buf, n_io, &n_io_done, eIO_WritePersist);
            switch ( status ) {
            case eIO_Success:
                CORE_LOGF(eLOG_Note,
                          ("TS2::write:"
                           " [%lu], status=%7s, n_io=%5lu, n_io_done=%5lu",
                           (unsigned long)i, IO_StatusStr(status),
                           (unsigned long)n_io, (unsigned long)n_io_done));
                assert(n_io_done > 0);
                break;
            case eIO_Closed:
                CORE_LOG(eLOG_Fatal, "TS2::write: connection closed");
                return;
            case eIO_Timeout:
                CORE_LOGF(eLOG_Note,
                          ("TS2::write:"
                           " [%lu] timeout expired: %5u sec, %6u usec",
                           (unsigned long)i, w_to.sec, w_to.usec));
                assert(n_io_done == 0);
                s_DoubleTimeout(&w_to);
                status = SOCK_SetTimeout(sock, eIO_Write, &w_to);
                assert(status == eIO_Success);
                break;
            default:
                CORE_LOGF(eLOG_Fatal,
                          ("TS2::write: status = %d", (int) status));
            } /* switch */

            n_io  -= n_io_done;
            x_buf += n_io_done;
        }
    }
}
Exemplo n.º 10
0
static void TEST__client_2(SOCK sock)
{
#define W_FIELD  10
#define N_FIELD  1000
#define N_REPEAT 10
#define N_RECONNECT 3
    EIO_Status status;
    size_t     n_io, n_io_done, i;
    char       buf[W_FIELD * N_FIELD + 1];

    CORE_LOGF(eLOG_Note,
              ("TEST__client_2(TC2) @:%hu",
               SOCK_GetLocalPort(sock, eNH_HostByteOrder)));

    /* fill out a buffer to send to server */
    memset(buf, 0, sizeof(buf));
    for (i = 0;  i < N_FIELD;  i++) {
        sprintf(buf + i * W_FIELD, "%10lu", (unsigned long)i);
    }

    /* send the buffer to server, then get it back */
    for (i = 0;  i < N_REPEAT;  i++) {
        char        buf1[sizeof(buf)];
        STimeout    w_to, r_to;
        int/*bool*/ w_timeout_on = (int)(i%2); /* if to start from     */
        int/*bool*/ r_timeout_on = (int)(i%2); /* zero or inf. timeout */
        char*       x_buf;

        /* set timeout */
        w_to.sec  = 0;
        w_to.usec = 0;
        status = SOCK_SetTimeout(sock, eIO_Write, w_timeout_on ? &w_to : 0);
        assert(status == eIO_Success);

        /* reconnect */
        if ((i % N_RECONNECT) == 0) {
            size_t j = i / N_RECONNECT;
            do {
                SOCK_SetDataLogging(sock, eOn);
                status = SOCK_Reconnect(sock, 0, 0, 0);
                SOCK_SetDataLogging(sock, eDefault);
                CORE_LOGF(eLOG_Note,
                          ("TC2::reconnect @:%hu: i=%lu, j=%lu, status=%s",
                           SOCK_GetLocalPort(sock, eNH_HostByteOrder),
                           (unsigned long) i, (unsigned long) j,
                           IO_StatusStr(status)));
                assert(status == eIO_Success);
                assert(SOCK_Status(sock, eIO_Read)  == eIO_Success);
                assert(SOCK_Status(sock, eIO_Write) == eIO_Success);

                /* give a break to let server reset the listening socket */
                X_SLEEP(1);
            } while ( j-- );
        }

        /* send */
        x_buf = buf;
        n_io = sizeof(buf);
        do {
            X_SLEEP(1);
            status = SOCK_Write(sock, x_buf, n_io,
                                &n_io_done, eIO_WritePersist);
            if (status == eIO_Closed)
                CORE_LOG(eLOG_Fatal, "TC2::write: connection closed");

            CORE_LOGF(eLOG_Note,
                      ("TC2::write:"
                       " i=%d, status=%7s, n_io=%5lu, n_io_done=%5lu"
                       " timeout(%d): %5u.%06us",
                       (int) i, IO_StatusStr(status),
                       (unsigned long) n_io, (unsigned long) n_io_done,
                       (int) w_timeout_on, w_to.sec, w_to.usec));
            if ( !w_timeout_on ) {
                assert(status == eIO_Success  &&  n_io_done == n_io);
            } else {
                const STimeout* x_to;
                assert(status == eIO_Success  ||  status == eIO_Timeout);
                x_to = SOCK_GetTimeout(sock, eIO_Write);
                assert(w_to.sec == x_to->sec  &&  w_to.usec == x_to->usec);
            }
            n_io  -= n_io_done;
            x_buf += n_io_done;
            if (status == eIO_Timeout)
                s_DoubleTimeout(&w_to);
            status = SOCK_SetTimeout(sock, eIO_Write, &w_to);
            assert(status == eIO_Success);
            w_timeout_on = 1/*true*/;
        } while ( n_io );

        /* get back the just sent data */
        r_to.sec  = 0;
        r_to.usec = 0;
        status = SOCK_SetTimeout(sock, eIO_Read, r_timeout_on ? &r_to : 0);
        assert(status == eIO_Success);

        x_buf = buf1;
        n_io = sizeof(buf1);
        do {
            if (i%2 == 0) {
                /* peek a little piece twice and compare */
                char   xx_buf1[128], xx_buf2[128];
                size_t xx_io_done1, xx_io_done2;
                if (SOCK_Read(sock, xx_buf1, sizeof(xx_buf1), &xx_io_done1,
                              eIO_ReadPeek) == eIO_Success  &&
                    SOCK_Read(sock, xx_buf2, xx_io_done1, &xx_io_done2,
                              eIO_ReadPeek) == eIO_Success) {
                    assert(xx_io_done1 >= xx_io_done2);
                    assert(memcmp(xx_buf1, xx_buf2, xx_io_done2) == 0);
                }
            }
            status = SOCK_Read(sock, x_buf, n_io, &n_io_done, eIO_ReadPlain);
            if (status == eIO_Closed) {
                assert(SOCK_Status(sock, eIO_Read) == eIO_Closed);
                CORE_LOG(eLOG_Fatal, "TC2::read: connection closed");
            }
            CORE_LOGF(eLOG_Note,
                      ("TC2::read: "
                       " i=%d, status=%7s, n_io=%5lu, n_io_done=%5lu"
                       " timeout(%d): %5u.%06us",
                       (int) i, IO_StatusStr(status),
                       (unsigned long) n_io, (unsigned long) n_io_done,
                       (int) r_timeout_on, r_to.sec, r_to.usec));
            if ( !r_timeout_on ) {
                assert(status == eIO_Success  &&  n_io_done > 0);
            } else {
                const STimeout* x_to;
                assert(status == eIO_Success  ||  status == eIO_Timeout);
                x_to = SOCK_GetTimeout(sock, eIO_Read);
                assert(r_to.sec == x_to->sec  &&  r_to.usec == x_to->usec);
            }

            n_io  -= n_io_done;
            x_buf += n_io_done;
            if (status == eIO_Timeout)
                s_DoubleTimeout(&r_to);
            status = SOCK_SetTimeout(sock, eIO_Read, &r_to);
            assert(status == eIO_Success);
            r_timeout_on = 1/*true*/;
        } while ( n_io );

        assert(memcmp(buf, buf1, sizeof(buf)) == 0);
    }
}
Exemplo n.º 11
0
int main(int argc, char** argv)
{
    /* Prepare to connect:  parse and check cmd.-line args, etc. */
    const char*    host        = argc > 1 ? argv[1]       : "";
    unsigned short port        = argc > 2 ? atoi(argv[2]) : CONN_PORT_HTTP;
    const char*    path        = argc > 3 ? argv[3]       : "";
    const char*    args        = argc > 4 ? argv[4]       : "";
    const char*    inp_file    = argc > 5 ? argv[5]       : "";
    const char*    user_header = argc > 6 ? argv[6]       : "";

    size_t   content_length;
    STimeout timeout;

    SOCK sock;
    EIO_Status status;
    char buffer[10000];

    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
                           fLOG_OmitNoteLevel | fLOG_DateTime);
    CORE_SetLOGFILE(stderr, 0/*false*/);

    SOCK_SetupSSL(NcbiSetupTls);

    fprintf(stderr, "Running...\n"
            "  Executable:      '%s'\n"
            "  URL host:        '%s'\n"
            "  URL port:         %hu\n"
            "  URL path:        '%s'\n"
            "  URL args:        '%s'\n"
            "  Input data file: '%s'\n"
            "  User header:     '%s'\n"
            "Response(if any) from the hit URL goes to standard output.\n\n",
            argv[0], host, port, path, args, inp_file, user_header);

    if ( argc < 4 ) {
        fprintf(stderr,
                "Usage:   %s host port path args inp_file [user_header]\n",
                argv[0]);
        CORE_LOG(eLOG_Fatal, "Two few arguments");
        return 1;
    }

    {{
        FILE *fp = fopen(inp_file, "rb");
        long offset;

        if ( !fp ) {
            CORE_LOGF(eLOG_Fatal, ("Non-existent file '%s'", inp_file));
            return 2;
        }
        if ( fseek(fp, 0, SEEK_END) != 0  ||  (offset = ftell(fp)) < 0 ) {
            CORE_LOGF(eLOG_Fatal,
                      ("Cannot obtain size of file '%s'", inp_file));
            return 2;
        }
        fclose(fp);
        content_length = (size_t) offset;
    }}

    timeout.sec  = 10;
    timeout.usec = 0;
    
    /* Connect */
    sock = URL_Connect(host, port, path, args, /*NCBI_FAKE_WARNING*/
                       eReqMethod_Any, content_length,
                       &timeout, &timeout, user_header, 1/*true*/,
                       port == CONN_PORT_HTTPS
                       ? fSOCK_LogDefault | fSOCK_Secure
                       : fSOCK_LogDefault);
    if ( !sock )
        return 3;

    {{ /* Pump data from the input file to socket */
        FILE* fp = fopen(inp_file, "rb");
        if ( !fp ) {
            CORE_LOGF(eLOG_Fatal, 
                      ("Cannot open file '%s' for reading", inp_file));
            return 4;
        }

        for (;;) {
            size_t n_written;
            size_t n_read = fread(buffer, 1, sizeof(buffer), fp);
            if ( n_read <= 0 ) {
                if ( content_length ) {
                    CORE_LOGF(eLOG_Fatal,
                              ("Cannot read last %lu bytes from file '%s'",
                               (unsigned long) content_length, inp_file));
                    return 5;
                }
                break;
            }

            assert(content_length >= n_read);
            content_length -= n_read;
            status = SOCK_Write(sock, buffer, n_read,
                                &n_written, eIO_WritePersist);
            if ( status != eIO_Success ) {
                CORE_LOGF(eLOG_Fatal,
                          ("Error writing to socket: %s",
                           IO_StatusStr(status)));
                return 6;
            }
        }

        fclose(fp);
    }}

    /* Read reply from socket, write it to STDOUT */
    {{
        size_t n_read;
        for (;;) {
            status = SOCK_Read(sock, buffer, sizeof(buffer), &n_read,
                               eIO_ReadPlain);
            if (status != eIO_Success)
                break;

            fwrite(buffer, 1, n_read, stdout);
        }

        if ( status != eIO_Closed ) {
            CORE_LOGF(eLOG_Error,
                      ("Read error after %ld byte(s) from socket: %s",
                       (long) content_length, IO_StatusStr(status)));
        }
        fprintf(stdout, "\n");
    }}

    /* Success:  close the socket, cleanup, and exit */
    SOCK_Close(sock);

    CORE_LOG(eLOG_Note, "TEST completed successfully");
    CORE_SetLOG(0);
    return 0;
}
Exemplo n.º 12
0
static EIO_Status s_VT_Open(CONNECTOR connector, const STimeout* timeout)
{
    SServiceConnector* uuu = (SServiceConnector*) connector->handle;
    SMetaConnector* meta = connector->meta;
    EIO_Status status;

    for (;;) {
        const SSERV_Info* info;
        SConnNetInfo* net_info;
        CONNECTOR conn;
        int stateless;

        assert(!uuu->meta.list  &&  !uuu->name  &&  !uuu->descr);
        if (!uuu->iter  &&  !s_OpenDispatcher(uuu)) {
            status = eIO_Closed;
            break;
        }

        if (uuu->net_info->firewall  &&  strcasecmp(uuu->iter->name, "local"))
            info = 0;
        else if (!(info = s_GetNextInfo(uuu))) {
            status = eIO_Closed;
            break;
        }

        if (!(net_info = ConnNetInfo_Clone(uuu->net_info))) {
            status = eIO_Unknown;
            break;
        }

        net_info->scheme = eURL_Unspec;
        conn = s_Open(uuu, timeout, info, net_info, 0/*!second_try*/);
        if (conn)
            uuu->descr = ConnNetInfo_URL(net_info);
        stateless = net_info->stateless;

        ConnNetInfo_Destroy(net_info);

        if (!conn) {
            if (!info) {
                status = eIO_Closed;
                break;
            }
            continue;
        }

        /* Setup the new connector on a temporary meta-connector... */
        memset(&uuu->meta, 0, sizeof(uuu->meta));
        METACONN_Add(&uuu->meta, conn);
        /* ...then link it in using current connection's meta */
        conn->meta = meta;
        conn->next = meta->list;
        meta->list = conn;

        if (!uuu->descr  &&  uuu->meta.descr)
            CONN_SET_METHOD(meta, descr, uuu->meta.descr, uuu->meta.c_descr);
        CONN_SET_METHOD    (meta, wait,  uuu->meta.wait,  uuu->meta.c_wait);
        CONN_SET_METHOD    (meta, write, uuu->meta.write, uuu->meta.c_write);
        CONN_SET_METHOD    (meta, flush, uuu->meta.flush, uuu->meta.c_flush);
        CONN_SET_METHOD    (meta, read,  uuu->meta.read,  uuu->meta.c_read);
        CONN_SET_METHOD    (meta, status,uuu->meta.status,uuu->meta.c_status);
        if (uuu->meta.get_type) {
            const char* type;
            if ((type = uuu->meta.get_type(uuu->meta.c_get_type)) != 0) {
                size_t slen = strlen(uuu->service);
                size_t tlen = strlen(type);
                char* name = (char*) malloc(slen + tlen + 2);
                if (name) {
                    memcpy(name,        uuu->service, slen);
                    name[slen++] = '/';
                    memcpy(name + slen, type,         tlen);
                    tlen += slen;
                    name[tlen]   = '\0';
                    uuu->name = name;
                }
            }
        }

        status = uuu->meta.open
            ? uuu->meta.open(uuu->meta.c_open, timeout) : eIO_Success;
        if (status == eIO_Success)
            break;

        if (!stateless  &&  (!info  ||  info->type == fSERV_Firewall)) {
            static const char kFWLink[] = { "http://www.ncbi.nlm.nih.gov"
                                            "/IEB/ToolBox/NETWORK"
                                            "/dispatcher.html#Firewalling"};
            CORE_LOGF_X(6, eLOG_Error,
                        ("[%s]  %s connection failed (%s) indicating possible "
                         "firewall configuration problem; please consult <%s>",
                         uuu->service, !info ? "Firewall" : "Stateful relay",
                         IO_StatusStr(status), kFWLink));
        }
        s_Close(connector, timeout, 0/*don't close dispatcher just as yet*/);
    }

    uuu->status = status;
    return status;
}
Exemplo n.º 13
0
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*/);
}
Exemplo n.º 14
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*/;
}
Exemplo n.º 15
0
int main(int argc, const char* argv[])
{
    const char* inp_file    = (argc > 5) ? argv[5] : "";
    const char* user_header = (argc > 6) ? argv[6] : "";

    SConnNetInfo* net_info;
    CONNECTOR     connector;
    CONN          conn;
    EIO_Status    status;

    char   buffer[100];
    size_t n_read, n_written;

    /* Prepare to connect:  parse and check cmd.-line args, etc. */
    s_Args.host         = (argc > 1) ? argv[1] : "";
    s_Args.port         = (argc > 2) ? argv[2] : "";
    s_Args.path         = (argc > 3) ? argv[3] : "";
    s_Args.args         = (argc > 4) ? argv[4] : "";

    fprintf(stderr, "Running '%s':\n"
            "  URL host:        '%s'\n"
            "  URL port:        '%s'\n"
            "  URL path:        '%s'\n"
            "  URL args:        '%s'\n"
            "  Input data file: '%s'\n"
            "  User header:     '%s'\n"
            "Reply(if any) from the hit URL goes to the standard output.\n\n",
            argv[0],
            s_Args.host, s_Args.port, s_Args.path, s_Args.args,
            inp_file, user_header);

    /* Log stream */
    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
                           fLOG_OmitNoteLevel | fLOG_DateTime);
    CORE_SetLOGFILE(stderr, 0/*false*/);

    /* Tune to the test URL using hard-coded pseudo-registry */
    CORE_SetREG( REG_Create(0, s_REG_Get, 0, 0, 0) );

    SOCK_SetupSSL(NcbiSetupTls);

    /* Usage */
    if (argc < 4) {
        fprintf(stderr,
                "Usage:   %s host port path [args] [inp_file] [user_header]\n"
                "Example: %s www.ncbi.nlm.nih.gov 80 "
                "/Service/bounce.cgi 'arg1+arg2+arg3'\n",
                argv[0], argv[0]);
        CORE_LOG(eLOG_Fatal, "Too few arguments");
        return 1;
    }

    /* Connect */
    if (atoi(s_Args.port) == CONN_PORT_HTTPS) {
        verify((net_info = ConnNetInfo_Create(0)) != 0);
        net_info->scheme = eURL_Https;
    } else
        net_info = 0;

    connector = HTTP_CreateConnector(net_info, user_header, 0);
    assert(connector);
    verify(CONN_Create(connector, &conn) == eIO_Success);

    ConnNetInfo_Destroy(net_info);

    /* If input file specified, then send its content (as HTTP request body) */
    if (*inp_file) {
        FILE* inp_fp;

        if (strcmp(inp_file, "-") != 0) {
            static const char kDevNull[] =
#ifdef NCBI_OS_MSWIN
                "NUL"
#else
                "/dev/null"
#endif /*NCBI_OS_MSWIN*/
                ;
            if (strcmp(inp_file, "+") == 0)
                inp_file = kDevNull;
            if (!(inp_fp = fopen(inp_file, "rb"))) {
                CORE_LOGF(eLOG_Fatal,
                          ("Cannot open file '%s' for reading", inp_file));
            }
        } else
            inp_fp = stdin;

        for (;;) {
            n_read = fread(buffer, 1, sizeof(buffer), inp_fp);
            if (n_read <= 0) {
                assert(feof(inp_fp));
                break; /* EOF */
            }

            status = CONN_Write(conn, buffer, n_read,
                                &n_written, eIO_WritePersist);
            if (status != eIO_Success) {
                CORE_LOGF(eLOG_Fatal,
                          ("Unable to write to URL: %s",IO_StatusStr(status)));
            }
            assert(n_written == n_read);
        }
        fclose(inp_fp);
    }

    /* Read reply from connection, write it to standard output */
    for (;;) {
        status = CONN_Read(conn,buffer,sizeof(buffer),&n_read,eIO_ReadPlain);
        if (status != eIO_Success)
            break;
        if (connector)
            puts("----- [BEGIN] HTTP Content -----");
        fwrite(buffer, 1, n_read, stdout);
        fflush(stdout);
        connector = 0;
    }
    if (!connector) {
        puts("\n----- [END] HTTP Content -----");
        fclose(stdout);
    }

    if (status != eIO_Closed) {
        CORE_LOGF(eLOG_Fatal,
                  ("Unable to read from URL: %s", IO_StatusStr(status)));
    }

    /* Success:  close the connection, cleanup, and exit */
    CONN_Close(conn);
    CORE_SetREG(0);
    CORE_LOG(eLOG_Note, "TEST completed successfully");
    CORE_SetLOG(0);
    return 0;
}
Exemplo n.º 16
0
/* Connect to the server specified by uuu->net_info, then compose and form
 * relevant HTTP header, and flush the accumulated output data(uuu->w_buf)
 * after the HTTP header. If connection/write unsuccessful, retry to reconnect
 * and send the data again until permitted by s_Adjust().
 */
static EIO_Status s_ConnectAndSend(SHttpConnector* uuu,
                                   EReadMode       read_mode)
{
    EIO_Status status;

    for (;;) {
        char* null = 0;

        if (!uuu->sock) {
            if ((status = s_Connect(uuu, read_mode)) != eIO_Success)
                break;
            assert(uuu->sock);
            uuu->read_header = 1/*true*/;
            uuu->shut_down = 0/*false*/;
            uuu->expected = 0;
            uuu->received = 0;
            uuu->code = 0;
        } else
            status = eIO_Success;

        if (uuu->w_len) {
            size_t off = BUF_Size(uuu->w_buf) - uuu->w_len;

            SOCK_SetTimeout(uuu->sock, eIO_Write, uuu->w_timeout);
            do {
                char   buf[4096];
                size_t n_written;
                size_t n_write = BUF_PeekAt(uuu->w_buf, off, buf, sizeof(buf));
                status = SOCK_Write(uuu->sock, buf, n_write,
                                    &n_written, eIO_WritePlain);
                if (status != eIO_Success)
                    break;
                uuu->w_len -= n_written;
                off        += n_written;
            } while (uuu->w_len);
        } else if (!uuu->shut_down)
            status = SOCK_Write(uuu->sock, 0, 0, 0, eIO_WritePlain);

        if (status == eIO_Success) {
            assert(uuu->w_len == 0);
            if (!uuu->shut_down) {
                /* 10/07/03: While this call here is perfectly legal, it could
                 * cause connection severed by a buggy CISCO load-balancer. */
                /* 10/28/03: CISCO's beta patch for their LB shows that the
                 * problem has been fixed; no more 2'30" drops in connections
                 * that shut down for write.  We still leave this commented
                 * out to allow unpatched clients to work seamlessly... */ 
                /*SOCK_Shutdown(uuu->sock, eIO_Write);*/
                uuu->shut_down = 1;
            }
            break;
        }

        if (status == eIO_Timeout  &&  uuu->w_timeout  &&
            !(uuu->w_timeout->sec | uuu->w_timeout->usec)) {
            break;
        }
        CORE_LOGF_X(6, eLOG_Error,
                    ("[HTTP]  Error writing body at offset %lu (%s)",
                     (unsigned long)(BUF_Size(uuu->w_buf) - uuu->w_len),
                     IO_StatusStr(status)));

        /* write failed; close and try to use another server */
        SOCK_Abort(uuu->sock);
        s_DropConnection(uuu, 0/*no wait*/);
        if (!s_Adjust(uuu, &null, read_mode)) {
            uuu->can_connect = eCC_None;
            status = eIO_Closed;
            break;
        }
    }

    return status;
}
Exemplo n.º 17
0
/* Parse HTTP header */
static EIO_Status s_ReadHeader(SHttpConnector* uuu,
                               char**          retry,
                               EReadMode       read_mode)
{
    ERetry     redirect = eRetry_None; 
    int        server_error = 0;
    int        http_status;
    EIO_Status status;
    char*      header;
    size_t     size;

    assert(uuu->sock  &&  uuu->read_header);
    *retry = 0;

    /* line by line HTTP header input */
    for (;;) {
        /* do we have full header yet? */
        size = BUF_Size(uuu->http);
        if (!(header = (char*) malloc(size + 1))) {
            CORE_LOGF_X(7, eLOG_Error,
                        ("[HTTP]  Cannot allocate header, %lu bytes",
                         (unsigned long) size));
            return eIO_Unknown;
        }
        verify(BUF_Peek(uuu->http, header, size) == size);
        header[size] = '\0';
        if (size >= 4  &&  strcmp(&header[size - 4], "\r\n\r\n") == 0)
            break/*full header captured*/;
        free(header);

        status = SOCK_StripToPattern(uuu->sock, "\r\n", 2, &uuu->http, 0);
        if (status != eIO_Success) {
            ELOG_Level level;
            if (status == eIO_Timeout) {
                const STimeout* tmo = SOCK_GetTimeout(uuu->sock, eIO_Read);
                if (!tmo)
                    level = eLOG_Error;
                else if (tmo->sec | tmo->usec)
                    level = eLOG_Warning;
                else if (read_mode != eRM_WaitCalled)
                    level = eLOG_Trace;
                else
                    return status;
            } else
                level = eLOG_Error;
            CORE_LOGF_X(8, level, ("[HTTP]  Error reading header (%s)",
                                   IO_StatusStr(status)));
            return status;
        }
    }
    /* the entire header has been read */
    uuu->read_header = 0/*false*/;
    status = eIO_Success;

    if (BUF_Read(uuu->http, 0, size) != size) {
        CORE_LOG_X(9, eLOG_Error, "[HTTP]  Cannot discard HTTP header buffer");
        status = eIO_Unknown;
        assert(0);
    }

    /* HTTP status must come on the first line of the response */
    if (sscanf(header, "HTTP/%*d.%*d %d ", &http_status) != 1 || !http_status)
        http_status = -1;
    if (http_status < 200  ||  299 < http_status) {
        server_error = http_status;
        if      (http_status == 301  ||  http_status == 302)
            redirect = eRetry_Redirect;
        else if (http_status == 401)
            redirect = eRetry_Authenticate;
        else if (http_status == 407)
            redirect = eRetry_ProxyAuthenticate;
        else if (http_status < 0  ||  http_status == 403 || http_status == 404)
            uuu->net_info->max_try = 0;
    }
    uuu->code = http_status < 0 ? -1 : http_status;

    if ((server_error  ||  !uuu->error_header)
        &&  uuu->net_info->debug_printout == eDebugPrintout_Some) {
        /* HTTP header gets printed as part of data logging when
           uuu->net_info->debug_printout == eDebugPrintout_Data. */
        const char* header_header;
        if (!server_error)
            header_header = "HTTP header";
        else if (uuu->flags & fHCC_KeepHeader)
            header_header = "HTTP header (error)";
        else if (uuu->code == 301  ||  uuu->code == 302)
            header_header = "HTTP header (moved)";
        else if (!uuu->net_info->max_try)
            header_header = "HTTP header (unrecoverable error)";
        else
            header_header = "HTTP header (server error, can retry)";
        CORE_DATA_X(19, header, size, header_header);
    }

    {{
        /* parsing "NCBI-Message" tag */
        static const char kNcbiMessageTag[] = "\n" HTTP_NCBI_MESSAGE " ";
        const char* s;
        for (s = strchr(header, '\n');  s  &&  *s;  s = strchr(s + 1, '\n')) {
            if (strncasecmp(s, kNcbiMessageTag, sizeof(kNcbiMessageTag)-1)==0){
                const char* message = s + sizeof(kNcbiMessageTag) - 1;
                while (*message  &&  isspace((unsigned char)(*message)))
                    message++;
                if (!(s = strchr(message, '\r')))
                    s = strchr(message, '\n');
                assert(s);
                do {
                    if (!isspace((unsigned char) s[-1]))
                        break;
                } while (--s > message);
                if (message != s) {
                    if (s_MessageHook) {
                        if (s_MessageIssued <= 0) {
                            s_MessageIssued = 1;
                            s_MessageHook(message);
                        }
                    } else {
                        s_MessageIssued = -1;
                        CORE_LOGF_X(10, eLOG_Critical,
                                    ("[NCBI-MESSAGE]  %.*s",
                                     (int)(s - message), message));
                    }
                }
                break;
            }
        }
    }}

    if (uuu->flags & fHCC_KeepHeader) {
        if (!BUF_Write(&uuu->r_buf, header, size)) {
            CORE_LOG_X(11, eLOG_Error, "[HTTP]  Cannot keep HTTP header");
            status = eIO_Unknown;
        }
        free(header);
        return status;
    }

    if (uuu->parse_http_hdr
        &&  !(*uuu->parse_http_hdr)(header, uuu->adjust_data, server_error)) {
        server_error = 1/*fake, but still boolean true*/;
    }

    if (redirect == eRetry_Redirect) {
        /* parsing "Location" pointer */
        static const char kLocationTag[] = "\nLocation: ";
        char* s;
        for (s = strchr(header, '\n');  s  &&  *s;  s = strchr(s + 1, '\n')) {
            if (strncasecmp(s, kLocationTag, sizeof(kLocationTag) - 1) == 0) {
                char* location = s + sizeof(kLocationTag) - 1;
                while (*location  &&  isspace((unsigned char)(*location)))
                    location++;
                if (!(s = strchr(location, '\r')))
                    s = strchr(location, '\n');
                assert(s);
                do {
                    if (!isspace((unsigned char) s[-1]))
                        break;
                } while (--s > location);
                if (s != location) {
                    size_t len = (size_t)(s - location);
                    memmove(header, location, len);
                    header[len] = '\0';
                    *retry = header;
                }
                break;
            }
        }
    } else if (redirect != eRetry_None) {
        /* parsing "Authenticate" tags */
        static const char kAuthenticateTag[] = "-Authenticate: ";
        char* s;
        for (s = strchr(header, '\n');  s  &&  *s;  s = strchr(s + 1, '\n')) {
            if (strncasecmp(s + (redirect == eRetry_Authenticate ? 4 : 6),
                            kAuthenticateTag, sizeof(kAuthenticateTag)-1)==0){
                if ((redirect == eRetry_Authenticate
                     &&  strncasecmp(s, "\nWWW",   4) != 0)  ||
                    (redirect == eRetry_ProxyAuthenticate
                     &&  strncasecmp(s, "\nProxy", 6) != 0)) {
                    continue;
                }
                /* TODO */
            }
        }
    } else if (!server_error) {
        static const char kContentLengthTag[] = "\nContent-Length: ";
        const char* s;
        for (s = strchr(header, '\n');  s  &&  *s;  s = strchr(s + 1, '\n')) {
            if (!strncasecmp(s,kContentLengthTag,sizeof(kContentLengthTag)-1)){
                const char* expected = s + sizeof(kContentLengthTag) - 1;
                while (*expected  &&  isspace((unsigned char)(*expected)))
                    expected++;
                if (!(s = strchr(expected, '\r')))
                    s = strchr(expected, '\n');
                assert(s);
                do {
                    if (!isspace((unsigned char) s[-1]))
                        break;
                } while (--s > expected);
                if (s != expected) {
                    char* e;
                    errno = 0;
                    uuu->expected = (size_t) strtol(expected, &e, 10);
                    if (errno  ||  e != s)
                        uuu->expected = 0;
                    else if (!uuu->expected)
                        uuu->expected = (size_t)(-1L);
                }
                break;
            }
        }
    }
    if (!*retry)
        free(header);

    /* skip & printout the content, if server error was flagged */
    if (server_error && uuu->net_info->debug_printout == eDebugPrintout_Some) {
        BUF   buf = 0;
        char* body;

        SOCK_SetTimeout(uuu->sock, eIO_Read, 0);
        /* read until EOF */
        SOCK_StripToPattern(uuu->sock, 0, 0, &buf, 0);
        if (!(size = BUF_Size(buf))) {
            CORE_LOG_X(12, eLOG_Trace,
                       "[HTTP]  No HTTP body received with this error");
        } else if ((body = (char*) malloc(size)) != 0) {
            size_t n = BUF_Read(buf, body, size);
            if (n != size) {
                CORE_LOGF_X(13, eLOG_Error,
                            ("[HTTP]  Cannot read server error "
                             "body from buffer (%lu out of %lu)",
                             (unsigned long) n, (unsigned long) size));
            }
            CORE_DATA_X(20, body, n, "Server error body");
            free(body);
        } else {
            CORE_LOGF_X(14, eLOG_Error,
                        ("[HTTP]  Cannot allocate server error "
                         "body, %lu bytes", (unsigned long) size));
        }
        BUF_Destroy(buf);
    }

    return server_error ? eIO_Unknown : status;
}
Exemplo n.º 18
0
NLM_EXTERN CONN QUERY_OpenUrlQuery (
  const char*     host_machine,
  Nlm_Uint2       host_port,
  const char*     host_path,
  const char*     arguments,
  const char*     appName,
  Nlm_Uint4       timeoutsec,
  EMIME_Type      type,
  EMIME_SubType   subtype,
  EMIME_Encoding  encoding,
  THCC_Flags      flags
)
{
  CONN           conn;
  CONNECTOR      connector;
  SConnNetInfo*  net_info;
  EIO_Status     status;

  if (StringHasNoText (host_path))
    return NULL;

  /* fill in connection info fields and create the connection */
  net_info = ConnNetInfo_Create(0);
  ASSERT ( net_info );

  x_SetupUserHeader (net_info, appName, type, subtype, encoding);

  if (StringDoesHaveText (host_machine)) {
    StringNCpy_0 (net_info->host, host_machine, sizeof (net_info->host));
  }
  if ( host_port ) {
    net_info->port = host_port;
  }
  StringNCpy_0 (net_info->path, host_path, sizeof (net_info->path));
  if (StringDoesHaveText (arguments)) {
    StringNCpy_0 (net_info->args, arguments, sizeof (net_info->args));
  }

  if (timeoutsec == (Nlm_Uint4)(-1L)) {
    net_info->timeout  = kInfiniteTimeout;
  } else if ( timeoutsec ) {
    net_info->tmo.sec  = timeoutsec;
    net_info->tmo.usec = timeoutsec;
    net_info->timeout  = &net_info->tmo;
  }

  connector = HTTP_CreateConnector (net_info, NULL, flags);

  ConnNetInfo_Destroy (net_info);

  if (connector == NULL) {
    ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenUrlQuery failed in HTTP_CreateConnector");
    conn = NULL;
  } else if ((status = CONN_Create (connector, &conn)) != eIO_Success) {
    ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenUrlQuery failed in CONN_Create: %s",
              IO_StatusStr (status));
    ASSERT (conn == NULL);
  }

  return conn;
}