Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions base/poco/Net/include/Poco/Net/HTTPChunkedStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace Net
~HTTPChunkedStreamBuf();
void close();

bool isComplete() const { return _chunk == std::char_traits<char>::eof(); }
bool isComplete(bool read_from_device_to_check_eof = false) noexcept;

protected:
int readFromDevice(char * buffer, std::streamsize length);
Expand All @@ -70,8 +70,6 @@ namespace Net
~HTTPChunkedIOS();
HTTPChunkedStreamBuf * rdbuf();

bool isComplete() const { return _buf.isComplete(); }

protected:
HTTPChunkedStreamBuf _buf;
};
Expand All @@ -83,6 +81,8 @@ namespace Net
public:
HTTPChunkedInputStream(HTTPSession & session);
~HTTPChunkedInputStream();

bool isComplete() { return _buf.isComplete(/*read_from_device_to_check_eof*/ true); }
};


Expand All @@ -92,6 +92,8 @@ namespace Net
public:
HTTPChunkedOutputStream(HTTPSession & session);
~HTTPChunkedOutputStream();

bool isComplete() { return _buf.isComplete(); }
};


Expand Down
29 changes: 26 additions & 3 deletions base/poco/Net/src/HTTPChunkedStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void HTTPChunkedStreamBuf::close()
sync();
_session.write("0\r\n\r\n", 5);

_chunk = std::char_traits<char>::eof();
_chunk = std::char_traits<char>::eof();
}
}

Expand Down Expand Up @@ -90,7 +90,7 @@ unsigned int HTTPChunkedStreamBuf::parseChunkLen()
if (size_t pos = line.find(';'); pos != std::string::npos)
line.resize(pos);

unsigned chunkLen;
unsigned chunkLen = 0;
if (NumberParser::tryParseHex(line, chunkLen))
return chunkLen;
else
Expand Down Expand Up @@ -118,6 +118,9 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)

if (_chunk > 0)
{
if (length == 0)
return 0;

if (length > _chunk) length = _chunk;
int n = _session.read(buffer, length);
if (n > 0)
Expand All @@ -128,7 +131,7 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
if (_chunk == 0) skipCRLF();
return n;
}
else
else
{
skipCRLF();
_chunk = eof;
Expand All @@ -137,6 +140,26 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
}


bool HTTPChunkedStreamBuf::isComplete(bool read_from_device_to_check_eof) noexcept
{
if (read_from_device_to_check_eof)
{
try
{
/// If the stream is closed without final last chunk
/// "Unexpected EOF" exception would be thrown
readFromDevice(nullptr, 0);
}
catch (...)
{
return false;
}
}

return _chunk == std::char_traits<char>::eof();
}


int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
_chunkBuffer.clear();
Expand Down
2 changes: 2 additions & 0 deletions src/Common/HTTPConnectionPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ class EndpointConnectionPool : public std::enable_shared_from_this<EndpointConne
response_stream = nullptr;
Session::setSendDataHooks();
Session::setReceiveDataHooks();
Session::setSendThrottler();
Session::setReceiveThrottler();

group->atConnectionDestroy();

Expand Down
16 changes: 16 additions & 0 deletions src/Common/tests/gtest_http_chunked_stream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <gtest/gtest.h>

#include <Poco/Net/HTTPChunkedStream.h>
#include <Poco/Net/HTTPClientSession.h>


TEST(HTTPChunkedStreamBuf, IsCompleteHandlesInvalidSocketException)
{
Poco::Net::HTTPClientSession session;
Poco::Net::HTTPChunkedStreamBuf buf(session, std::ios::in);

/// Default-initialized socket throws InvalidSocketException in SocketImpl::receiveBytes,
/// which HTTPChunkedStreamBuf::isComplete should swallow and return false.
bool complete = buf.isComplete(true);
ASSERT_FALSE(complete);
}
Loading