[Asio] Match condition based on asio::streambuf length

Hello, I'm attempting to write a TCP-based server that can interpret a protocol that has a prepended length followed by variable length data. To do this, I'm using async_read_until along with an asio::streambuf. In order to ensure that there is enough data in the buffer for my next async read handler in the chain, I've written a match condition that will return true if there is enough data already in the streambuf to satisfy the read: class read_until_length { public: explicit read_until_length(size_t len) : m_len(len) { } template<typename Iterator> std::pair<Iterator, bool> operator()(Iterator begin, Iterator end) const { Iterator i = begin; const size_t buffer_len = std::distance(begin,end); if(buffer_len >= m_len) { std::advance(i, m_len); return std::make_pair(i, true); } else return std::make_pair(end, false); } private: size_t m_len; }; And then I use it in chained calls to async_read_until as such: Connection::start() { // Call our next handler when we have received at least 4 bytes (which represents the payload length that will follow) boost::async_read_until(m_socket, // boost::asio::ip::tcp::socket m_data, // boost::asio::streambuf read_until_length(4), boost::bind(&Connection::read_element, this, boost::asio::placeholders::error)); } Connection::read_length(boost::system::error_code& error) { // Read out the 4 byte size header size_t length = 0; memcpy(&length, &*boost::asio::buffers_begin(m_data.data()), sizeof(size_t)); m_data.consume(sizeof(size_t)); // Read out the variable length data next now that we know the size of it boost::asio::async_read_until(m_socket, m_data, read_until_length(length), boost::bind(&Connection::read_data this, length, boost::asio::placeholders::error)); } Connection::read_data(size_t length, boost::system::error_code& error) { // Consume the payload of length bytes... } The problem that I'm having is that async_read_until() performs two checks on the match condition. The first (boost/asio/impl/read_until.ipp:954) is to see if the iterator returned from the match condition is at the end of the buffer. If that is true, it does not post the next handler and assumes that not enough data has been read from the socket. This causes a problem when there is exactly enough data in the streambuf with the match condition as written above. It seems that returning true from the match condition (in the second part of the std::pair<>) should still post a handler since the condition was matched and it shouldn't be overridden by the iterator being at the end of the buffer. Is there a way to use async_read_until and a custom match condition to match the exact size of the streambuf? Thanks in advance. --Chet
participants (1)
-
Chet S