Hello all,

once again I find myself struggling with asio streambufs but wanted to ask here before chicken out to char buffers again.
My problem is that I cannot read more than one protocol loop successfully.

I got a TCP connection here that continuously receives messages on a simple protocol like that:

header_size CRLF
header             (contains payload size)
payload

<repeat>

I thought this is a prime use case for reading into a streambuf as I can easily deal with additional data being in there and the client pushing as fast as it can. 

Here is what I do (simplified quite a bit, sorry for copy and paste and simplify errors):

(m_socket and m_streambuf are only used by one io_context, one thread, no races as far as I can tell)



void read_header_size() {

  asio::async_read_until(m_socket, m_streambuf, "\r\n",
    [self](const boost::system::error_code, const std::size_t) {
        // < handle error skipped >
        std::string hsizestr;
        hsizestr.reserve(32);
        {
            std::istream is(&self->m_streambuf);
            std::getline(is, hsizestr);
        }
        std::size_t header_size = parse(hsizestr);
        self->read_header(header_size);
  });
}


void read_header(const std::size_t n_header_size) {

  asio::async_read(m_socket, m_streambuf, boost::asio::transfer_exactly(n_header_size),
    [self, packet, n_header_size](const boost::system::error_code, const std::size_t) {

        // < handle error skipped >
        // Tried two versions of parsing the header (manual consume and istreams of various sorts)
        // manual consume:
        size_t payload_size = parse_header(n_streambuf.data().data(), n_header_size)) {
n_streambuf.consume(n_header_size);

        self->read_payload(payload_size);
    });
}

void read_payload(const std::size_t n_payload_size) {
  asio::async_read(m_socket, m_streambuf, boost::asio::transfer_exactly(payload_size),
    [self, n_packet, packet_size](const boost::system::error_code, const std::size_t) {
         // < handle error skipped >
         {
    std::istream is(&self->m_streambuf, std::ios::binary);
            is.read(target_buffer, target_buffer_size);                // target buffer is elsewhere and well guarded
         }

         // read next message
         self->read_header_size();
    });
}


When I run this and make sure the client pushes at least 2 packets I can safely receive and process the first but after that the next asnc_read() in read_header never returns. As in never calls its handler. From debugging and looking at the streambuf I can reasonably assume the buffer contains all the data after the first async_read_until because the packages are very small (only about 60 bytes total).
This leads me to believe the transfer_exactly don't return unless something is actually really transferred. But if such is the case, why does the first loop succeed? 

I am quite lost here. If anybody has some suggestion it is much appreciated.

Thanks a bunch!
Stephan