(websocket) use persistent member variable as temp variables to encode/decode zlib messages in order to reduce transient allocations
This commit is contained in:
parent
c57cf413fb
commit
37a054723a
@ -1,6 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All changes to this project will be documented in this file.
|
All changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [9.2.4] - 2020-04-13
|
||||||
|
|
||||||
|
(websocket) use persistent member variable as temp variables to encode/decode zlib messages in order to reduce transient allocations
|
||||||
|
|
||||||
## [9.2.3] - 2020-04-13
|
## [9.2.3] - 2020-04-13
|
||||||
|
|
||||||
(ws) add a --runtime option to ws cobra_subscribe to optionally limit how much time it will run
|
(ws) add a --runtime option to ws cobra_subscribe to optionally limit how much time it will run
|
||||||
|
@ -19,7 +19,7 @@ namespace ix
|
|||||||
struct WebSocketMessage
|
struct WebSocketMessage
|
||||||
{
|
{
|
||||||
WebSocketMessageType type;
|
WebSocketMessageType type;
|
||||||
std::string str;
|
const std::string& str;
|
||||||
size_t wireSize;
|
size_t wireSize;
|
||||||
WebSocketErrorInfo errorInfo;
|
WebSocketErrorInfo errorInfo;
|
||||||
WebSocketOpenInfo openInfo;
|
WebSocketOpenInfo openInfo;
|
||||||
@ -34,7 +34,7 @@ namespace ix
|
|||||||
WebSocketCloseInfo c,
|
WebSocketCloseInfo c,
|
||||||
bool b = false)
|
bool b = false)
|
||||||
: type(t)
|
: type(t)
|
||||||
, str(std::move(s))
|
, str(s)
|
||||||
, wireSize(w)
|
, wireSize(w)
|
||||||
, errorInfo(e)
|
, errorInfo(e)
|
||||||
, openInfo(o)
|
, openInfo(o)
|
||||||
|
@ -87,6 +87,9 @@ namespace ix
|
|||||||
//
|
//
|
||||||
size_t output;
|
size_t output;
|
||||||
|
|
||||||
|
// Clear output
|
||||||
|
out.clear();
|
||||||
|
|
||||||
if (in.empty())
|
if (in.empty())
|
||||||
{
|
{
|
||||||
// See issue #167
|
// See issue #167
|
||||||
@ -174,6 +177,9 @@ namespace ix
|
|||||||
_inflateState.avail_in = (uInt) inFixed.size();
|
_inflateState.avail_in = (uInt) inFixed.size();
|
||||||
_inflateState.next_in = (unsigned char*) (const_cast<char*>(inFixed.data()));
|
_inflateState.next_in = (unsigned char*) (const_cast<char*>(inFixed.data()));
|
||||||
|
|
||||||
|
// Clear output
|
||||||
|
out.clear();
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
_inflateState.avail_out = (uInt) _compressBufferSize;
|
_inflateState.avail_out = (uInt) _compressBufferSize;
|
||||||
|
@ -62,7 +62,7 @@ namespace ix
|
|||||||
WebSocketTransport::WebSocketTransport()
|
WebSocketTransport::WebSocketTransport()
|
||||||
: _useMask(true)
|
: _useMask(true)
|
||||||
, _blockingSend(false)
|
, _blockingSend(false)
|
||||||
, _compressedMessage(false)
|
, _receivedMessageCompressed(false)
|
||||||
, _readyState(ReadyState::CLOSED)
|
, _readyState(ReadyState::CLOSED)
|
||||||
, _closeCode(WebSocketCloseConstants::kInternalErrorCode)
|
, _closeCode(WebSocketCloseConstants::kInternalErrorCode)
|
||||||
, _closeReason(WebSocketCloseConstants::kInternalErrorMessage)
|
, _closeReason(WebSocketCloseConstants::kInternalErrorMessage)
|
||||||
@ -493,7 +493,7 @@ namespace ix
|
|||||||
? MessageKind::MSG_TEXT
|
? MessageKind::MSG_TEXT
|
||||||
: MessageKind::MSG_BINARY;
|
: MessageKind::MSG_BINARY;
|
||||||
|
|
||||||
_compressedMessage = _enablePerMessageDeflate && ws.rsv1;
|
_receivedMessageCompressed = _enablePerMessageDeflate && ws.rsv1;
|
||||||
|
|
||||||
// Continuation message needs to follow a non-fin TEXT or BINARY message
|
// Continuation message needs to follow a non-fin TEXT or BINARY message
|
||||||
if (!_chunks.empty())
|
if (!_chunks.empty())
|
||||||
@ -516,9 +516,9 @@ namespace ix
|
|||||||
if (ws.fin && _chunks.empty())
|
if (ws.fin && _chunks.empty())
|
||||||
{
|
{
|
||||||
emitMessage(
|
emitMessage(
|
||||||
_fragmentedMessageKind, frameData, _compressedMessage, onMessageCallback);
|
_fragmentedMessageKind, frameData, _receivedMessageCompressed, onMessageCallback);
|
||||||
|
|
||||||
_compressedMessage = false;
|
_receivedMessageCompressed = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -535,11 +535,11 @@ namespace ix
|
|||||||
{
|
{
|
||||||
emitMessage(_fragmentedMessageKind,
|
emitMessage(_fragmentedMessageKind,
|
||||||
getMergedChunks(),
|
getMergedChunks(),
|
||||||
_compressedMessage,
|
_receivedMessageCompressed,
|
||||||
onMessageCallback);
|
onMessageCallback);
|
||||||
|
|
||||||
_chunks.clear();
|
_chunks.clear();
|
||||||
_compressedMessage = false;
|
_receivedMessageCompressed = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -712,17 +712,16 @@ namespace ix
|
|||||||
// When the RSV1 bit is 1 it means the message is compressed
|
// When the RSV1 bit is 1 it means the message is compressed
|
||||||
if (compressedMessage && messageKind != MessageKind::FRAGMENT)
|
if (compressedMessage && messageKind != MessageKind::FRAGMENT)
|
||||||
{
|
{
|
||||||
std::string decompressedMessage;
|
bool success = _perMessageDeflate->decompress(message, _decompressedMessage);
|
||||||
bool success = _perMessageDeflate->decompress(message, decompressedMessage);
|
|
||||||
|
|
||||||
if (messageKind == MessageKind::MSG_TEXT && !validateUtf8(decompressedMessage))
|
if (messageKind == MessageKind::MSG_TEXT && !validateUtf8(_decompressedMessage))
|
||||||
{
|
{
|
||||||
close(WebSocketCloseConstants::kInvalidFramePayloadData,
|
close(WebSocketCloseConstants::kInvalidFramePayloadData,
|
||||||
WebSocketCloseConstants::kInvalidFramePayloadDataMessage);
|
WebSocketCloseConstants::kInvalidFramePayloadDataMessage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
onMessageCallback(decompressedMessage, wireSize, !success, messageKind);
|
onMessageCallback(_decompressedMessage, wireSize, !success, messageKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -759,7 +758,6 @@ namespace ix
|
|||||||
|
|
||||||
size_t payloadSize = message.size();
|
size_t payloadSize = message.size();
|
||||||
size_t wireSize = message.size();
|
size_t wireSize = message.size();
|
||||||
std::string compressedMessage;
|
|
||||||
bool compressionError = false;
|
bool compressionError = false;
|
||||||
|
|
||||||
std::string::const_iterator message_begin = message.begin();
|
std::string::const_iterator message_begin = message.begin();
|
||||||
@ -767,7 +765,7 @@ namespace ix
|
|||||||
|
|
||||||
if (compress)
|
if (compress)
|
||||||
{
|
{
|
||||||
if (!_perMessageDeflate->compress(message, compressedMessage))
|
if (!_perMessageDeflate->compress(message, _compressedMessage))
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
compressionError = true;
|
compressionError = true;
|
||||||
@ -776,10 +774,10 @@ namespace ix
|
|||||||
return WebSocketSendInfo(success, compressionError, payloadSize, wireSize);
|
return WebSocketSendInfo(success, compressionError, payloadSize, wireSize);
|
||||||
}
|
}
|
||||||
compressionError = false;
|
compressionError = false;
|
||||||
wireSize = compressedMessage.size();
|
wireSize = _compressedMessage.size();
|
||||||
|
|
||||||
message_begin = compressedMessage.begin();
|
message_begin = _compressedMessage.begin();
|
||||||
message_end = compressedMessage.end();
|
message_end = _compressedMessage.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -165,7 +165,7 @@ namespace ix
|
|||||||
MessageKind _fragmentedMessageKind;
|
MessageKind _fragmentedMessageKind;
|
||||||
|
|
||||||
// Ditto for whether a message is compressed
|
// Ditto for whether a message is compressed
|
||||||
bool _compressedMessage;
|
bool _receivedMessageCompressed;
|
||||||
|
|
||||||
// Fragments are 32K long
|
// Fragments are 32K long
|
||||||
static constexpr size_t kChunkSize = 1 << 15;
|
static constexpr size_t kChunkSize = 1 << 15;
|
||||||
@ -189,6 +189,9 @@ namespace ix
|
|||||||
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
|
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
|
||||||
std::atomic<bool> _enablePerMessageDeflate;
|
std::atomic<bool> _enablePerMessageDeflate;
|
||||||
|
|
||||||
|
std::string _decompressedMessage;
|
||||||
|
std::string _compressedMessage;
|
||||||
|
|
||||||
// Used to control TLS connection behavior
|
// Used to control TLS connection behavior
|
||||||
SocketTLSOptions _socketTLSOptions;
|
SocketTLSOptions _socketTLSOptions;
|
||||||
|
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IX_WEBSOCKET_VERSION "9.2.3"
|
#define IX_WEBSOCKET_VERSION "9.2.4"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user