Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:ClickHouse ClickHouse Poco HTTPSession Impl

From Leeroopedia


base/poco/Net/src/HTTPSession.cpp:1-308 ClickHouse_ClickHouse ClickHouse_ClickHouse_HTTP_Client_Communication

This page documents the implementation details of the `HTTPSession` class. The corresponding header is already documented under the ClickHouse_ClickHouse_HTTP_Client_Communication principle.

Purpose

Implements the `Poco::Net::HTTPSession` class, which manages the underlying TCP socket for HTTP client and server communication. It provides buffered reading, socket lifecycle management (connect, close, abort, detach, attach), timeout configuration, and data transfer hooks for throttling and monitoring.

Code Reference

Buffered Reading

The session maintains an internal buffer (`HTTP_DEFAULT_BUFFER_SIZE` bytes) for efficient character-at-a-time reading. The `get`, `peek`, and `read` methods consume from this buffer and refill it from the socket as needed:

int HTTPSession::get()
{
    if (_pCurrent == _pEnd)
        refill();
    if (_pCurrent < _pEnd)
        return *_pCurrent++;
    else
        return std::char_traits<char>::eof();
}

void HTTPSession::refill()
{
    if (!_pBuffer)
    {
        _pBuffer = std::make_unique<char[]>(HTTP_DEFAULT_BUFFER_SIZE);
    }
    _pCurrent = _pEnd = _pBuffer.get();
    int n = receive(_pBuffer.get(), HTTP_DEFAULT_BUFFER_SIZE);
    _pEnd += n;
}

Socket Connection

The `connect` method establishes the TCP connection and configures socket parameters:

void HTTPSession::connect(const SocketAddress& address)
{
    _socket.connect(address, _connectionTimeout);
    _socket.setReceiveTimeout(_receiveTimeout);
    _socket.setSendTimeout(_sendTimeout);
    _socket.setReceiveThrottler(_receiveThrottler);
    _socket.setSendThrottler(_sendThrottler);
    _socket.setNoDelay(true);
    // Clear leftover buffer data from previous (failed) request
    _pCurrent = _pEnd = _pBuffer.get();
}

Data Transfer with Hooks

Both `write` and `receive` support data hooks for monitoring and throttling:

int HTTPSession::write(const char* buffer, std::streamsize length)
{
    try
    {
        if (_sendDataHooks)
            _sendDataHooks->atStart((int) length);
        int result = _socket.sendBytes(buffer, (int) length);
        if (_sendDataHooks)
            _sendDataHooks->atFinish(result);
        return result;
    }
    catch (Poco::Exception& exc)
    {
        if (_sendDataHooks)
            _sendDataHooks->atFail();
        setException(exc);
        throw;
    }
}

Timeout Configuration

The `setTimeout` method supports separate connection, send, and receive timeouts. It applies socket-level timeouts only if the value has changed and the socket is connected:

void HTTPSession::setTimeout(const Poco::Timespan& connectionTimeout,
    const Poco::Timespan& sendTimeout,
    const Poco::Timespan& receiveTimeout)
{
    _connectionTimeout = connectionTimeout;
    if (_sendTimeout.totalMicroseconds() != sendTimeout.totalMicroseconds()) {
        _sendTimeout = sendTimeout;
        if (connected())
            _socket.setSendTimeout(_sendTimeout);
    }
    // similar for receiveTimeout
}

I/O Contract

Input Output Side Effects
`SocketAddress` via `connect` None Establishes TCP connection; sets timeouts, throttlers, and TCP_NODELAY; clears buffer
Buffer via `get` / `peek` / `read` Next character(s) or EOF Reads from socket on buffer underflow; triggers receive hooks
Buffer via `write` Bytes sent count Sends to socket; triggers send hooks; stores exception on failure
`Poco::Timespan` via `setTimeout` None Updates socket-level timeouts if connected; silently catches exceptions in release builds
`abort` None Shuts down and closes the socket
`detachSocket` Previous `StreamSocket` Replaces internal socket with a new default socket
`attachSocket` None Replaces internal socket and configures throttlers
`drainBuffer` Remaining buffer contents in `Poco::Buffer<char>&` Resets buffer pointers

Usage Examples

// Typical usage within HTTPClientSession (subclass of HTTPSession)
Poco::Net::HTTPClientSession session("www.example.com");
session.setTimeout(Poco::Timespan(5, 0));  // 5 second timeout for all operations
session.setKeepAlive(true);

// Low-level read
int ch = session.get();  // reads one character from buffered socket

// Socket detach/attach for connection pooling
Poco::Net::StreamSocket sock = session.detachSocket();
// ... reuse sock later ...
session.attachSocket(sock);

Internal Details

  • The buffer is lazily allocated on first `refill` call using `std::make_unique<char[]>`.
  • The `connected` method checks `_socket.impl()->initialized()` rather than attempting an I/O operation.
  • Exception management uses `setException` / `clearException` with a cloned `Poco::Exception*` stored on the heap. The destructor deletes it.
  • The `keepAlive` flag is advisory; it informs HTTP message framing but does not directly control socket-level `SO_KEEPALIVE`.
  • In release builds (`NDEBUG` defined), `setTimeout` silently catches `NetException` from socket operations, as some socket implementations may reject timeout changes.
  • The `drainBuffer` method copies remaining unread buffer contents into a `Poco::Buffer<char>` and resets the internal buffer pointers.

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment