mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 08:31:43 +02:00
fixed GH #1212: Lost WebSocket Frames after Client Websocket Handshake is complete
This commit is contained in:
@@ -238,4 +238,11 @@ void HTTPSession::attachSessionData(const Poco::Any& data)
|
||||
}
|
||||
|
||||
|
||||
void HTTPSession::drainBuffer(Poco::Buffer<char>& buffer)
|
||||
{
|
||||
buffer.assign(_pCurrent, static_cast<std::size_t>(_pEnd - _pCurrent));
|
||||
_pCurrent = _pEnd;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Poco/Net/HTTPServerRequestImpl.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/Net/HTTPClientSession.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include "Poco/MemoryStream.h"
|
||||
@@ -137,7 +138,9 @@ WebSocketImpl* WebSocket::accept(HTTPServerRequest& request, HTTPServerResponse&
|
||||
response.set("Sec-WebSocket-Accept", computeAccept(key));
|
||||
response.setContentLength(0);
|
||||
response.send().flush();
|
||||
return new WebSocketImpl(static_cast<StreamSocketImpl*>(static_cast<HTTPServerRequestImpl&>(request).detachSocket().impl()), false);
|
||||
|
||||
HTTPServerRequestImpl& requestImpl = static_cast<HTTPServerRequestImpl&>(request);
|
||||
return new WebSocketImpl(static_cast<StreamSocketImpl*>(requestImpl.detachSocket().impl()), requestImpl.session(), false);
|
||||
}
|
||||
else throw WebSocketException("No WebSocket handshake", WS_ERR_NO_HANDSHAKE);
|
||||
}
|
||||
@@ -205,7 +208,7 @@ WebSocketImpl* WebSocket::completeHandshake(HTTPClientSession& cs, HTTPResponse&
|
||||
std::string accept = response.get("Sec-WebSocket-Accept", "");
|
||||
if (accept != computeAccept(key))
|
||||
throw WebSocketException("Invalid or missing Sec-WebSocket-Accept header in handshake response", WS_ERR_HANDSHAKE_ACCEPT);
|
||||
return new WebSocketImpl(static_cast<StreamSocketImpl*>(cs.detachSocket().impl()), true);
|
||||
return new WebSocketImpl(static_cast<StreamSocketImpl*>(cs.detachSocket().impl()), cs, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Poco/Net/WebSocketImpl.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
#include "Poco/Net/HTTPSession.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include "Poco/BinaryReader.h"
|
||||
@@ -29,14 +30,17 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, bool mustMaskPayload):
|
||||
WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& session, bool mustMaskPayload):
|
||||
StreamSocketImpl(pStreamSocketImpl->sockfd()),
|
||||
_pStreamSocketImpl(pStreamSocketImpl),
|
||||
_buffer(0),
|
||||
_bufferOffset(0),
|
||||
_frameFlags(0),
|
||||
_mustMaskPayload(mustMaskPayload)
|
||||
{
|
||||
poco_check_ptr(pStreamSocketImpl);
|
||||
_pStreamSocketImpl->duplicate();
|
||||
session.drainBuffer(_buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -192,12 +196,12 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
|
||||
|
||||
int WebSocketImpl::receiveNBytes(void* buffer, int bytes)
|
||||
{
|
||||
int received = _pStreamSocketImpl->receiveBytes(reinterpret_cast<char*>(buffer), bytes);
|
||||
int received = receiveSomeBytes(reinterpret_cast<char*>(buffer), bytes);
|
||||
if (received > 0)
|
||||
{
|
||||
while (received < bytes)
|
||||
{
|
||||
int n = _pStreamSocketImpl->receiveBytes(reinterpret_cast<char*>(buffer) + received, bytes - received);
|
||||
int n = receiveSomeBytes(reinterpret_cast<char*>(buffer) + received, bytes - received);
|
||||
if (n > 0)
|
||||
received += n;
|
||||
else
|
||||
@@ -208,6 +212,23 @@ int WebSocketImpl::receiveNBytes(void* buffer, int bytes)
|
||||
}
|
||||
|
||||
|
||||
int WebSocketImpl::receiveSomeBytes(char* buffer, int bytes)
|
||||
{
|
||||
int n = _buffer.size() - _bufferOffset;
|
||||
if (n > 0)
|
||||
{
|
||||
if (bytes < n) n = bytes;
|
||||
std::memcpy(buffer, _buffer.begin() + _bufferOffset, n);
|
||||
_bufferOffset += n;
|
||||
return n;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _pStreamSocketImpl->receiveBytes(buffer, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SocketImpl* WebSocketImpl::acceptConnection(SocketAddress& clientAddr)
|
||||
{
|
||||
throw Poco::InvalidAccessException("Cannot acceptConnection() on a WebSocketImpl");
|
||||
|
||||
Reference in New Issue
Block a user