mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-26 02:18:04 +01:00
Add WebSocket::receiveFrame() that appends to a Poco::Buffer<char>
This commit is contained in:
@@ -104,7 +104,7 @@ int WebSocketImpl::sendBytes(const void* buffer, int length, int flags)
|
||||
}
|
||||
|
||||
|
||||
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
|
||||
int WebSocketImpl::receiveHeader(char mask[4], bool& useMask)
|
||||
{
|
||||
char header[MAX_HEADER_LENGTH];
|
||||
int n = receiveNBytes(header, 2);
|
||||
@@ -114,82 +114,100 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
|
||||
return n;
|
||||
}
|
||||
poco_assert (n == 2);
|
||||
Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]);
|
||||
int maskOffset = 0;
|
||||
if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4;
|
||||
lengthByte &= 0x7f;
|
||||
if (lengthByte > 0 || maskOffset > 0)
|
||||
{
|
||||
if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH)
|
||||
{
|
||||
n = receiveNBytes(header + 2, lengthByte + maskOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2);
|
||||
}
|
||||
if (n <= 0) throw WebSocketException("Incomplete header received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
|
||||
n += 2;
|
||||
}
|
||||
Poco::MemoryInputStream istr(header, n);
|
||||
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
|
||||
Poco::UInt8 flags;
|
||||
char mask[4];
|
||||
reader >> flags >> lengthByte;
|
||||
Poco::UInt8 flags = static_cast<Poco::UInt8>(header[0]);
|
||||
_frameFlags = flags;
|
||||
int payloadLength = 0;
|
||||
int payloadOffset = 2;
|
||||
if ((lengthByte & 0x7f) == 127)
|
||||
Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]);
|
||||
useMask = ((lengthByte & FRAME_FLAG_MASK) != 0);
|
||||
int payloadLength;
|
||||
lengthByte &= 0x7f;
|
||||
if (lengthByte == 127)
|
||||
{
|
||||
n = receiveNBytes(header + 2, 8);
|
||||
if (n <= 0)
|
||||
{
|
||||
_frameFlags = 0;
|
||||
return n;
|
||||
}
|
||||
Poco::MemoryInputStream istr(header + 2, 8);
|
||||
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
|
||||
Poco::UInt64 l;
|
||||
reader >> l;
|
||||
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %Lu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
|
||||
payloadLength = static_cast<int>(l);
|
||||
payloadOffset += 8;
|
||||
}
|
||||
else if ((lengthByte & 0x7f) == 126)
|
||||
} else if (lengthByte == 126)
|
||||
{
|
||||
n = receiveNBytes(header + 2, 2);
|
||||
if (n <= 0)
|
||||
{
|
||||
_frameFlags = 0;
|
||||
return n;
|
||||
}
|
||||
Poco::MemoryInputStream istr(header + 2, 2);
|
||||
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
|
||||
Poco::UInt16 l;
|
||||
reader >> l;
|
||||
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
|
||||
payloadLength = static_cast<int>(l);
|
||||
payloadOffset += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Poco::UInt8 l = lengthByte & 0x7f;
|
||||
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %u", unsigned(l)), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
|
||||
payloadLength = static_cast<int>(l);
|
||||
payloadLength = lengthByte;
|
||||
}
|
||||
if (lengthByte & FRAME_FLAG_MASK)
|
||||
|
||||
if (useMask)
|
||||
{
|
||||
reader.readRaw(mask, 4);
|
||||
payloadOffset += 4;
|
||||
n = receiveNBytes(mask, 4);
|
||||
if (n <= 0)
|
||||
{
|
||||
_frameFlags = 0;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
int received = 0;
|
||||
if (payloadOffset < n)
|
||||
|
||||
return payloadLength;
|
||||
}
|
||||
|
||||
|
||||
int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask)
|
||||
{
|
||||
int received = receiveNBytes(reinterpret_cast<char*>(buffer), payloadLength);
|
||||
if (received <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
|
||||
|
||||
if (useMask)
|
||||
{
|
||||
std::memcpy(buffer, header + payloadOffset, n - payloadOffset);
|
||||
received = n - payloadOffset;
|
||||
}
|
||||
if (received < payloadLength)
|
||||
{
|
||||
n = receiveNBytes(reinterpret_cast<char*>(buffer) + received, payloadLength - received);
|
||||
if (n <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
|
||||
received += n;
|
||||
}
|
||||
if (lengthByte & FRAME_FLAG_MASK)
|
||||
{
|
||||
char* p = reinterpret_cast<char*>(buffer);
|
||||
for (int i = 0; i < received; i++)
|
||||
{
|
||||
p[i] ^= mask[i % 4];
|
||||
buffer[i] ^= mask[i % 4];
|
||||
}
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
|
||||
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
|
||||
{
|
||||
char mask[4];
|
||||
bool useMask;
|
||||
int payloadLength = receiveHeader(mask, useMask);
|
||||
if (payloadLength <= 0)
|
||||
return payloadLength;
|
||||
if (payloadLength > length)
|
||||
throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", payloadLength), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
|
||||
return receivePayload(reinterpret_cast<char*>(buffer), payloadLength, mask, useMask);
|
||||
}
|
||||
|
||||
|
||||
int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int)
|
||||
{
|
||||
char mask[4];
|
||||
bool useMask;
|
||||
int payloadLength = receiveHeader(mask, useMask);
|
||||
if (payloadLength <= 0)
|
||||
return payloadLength;
|
||||
int oldSize = buffer.size();
|
||||
buffer.resize(oldSize + payloadLength);
|
||||
return receivePayload(buffer.begin() + oldSize, payloadLength, mask, useMask);
|
||||
}
|
||||
|
||||
|
||||
int WebSocketImpl::receiveNBytes(void* buffer, int bytes)
|
||||
{
|
||||
int received = _pStreamSocketImpl->receiveBytes(reinterpret_cast<char*>(buffer), bytes);
|
||||
|
||||
Reference in New Issue
Block a user