From e3d0c899d3f0d0d548e9d40307052dc2e738511c Mon Sep 17 00:00:00 2001 From: Kumamon38 Date: Thu, 18 Apr 2019 19:02:31 +0200 Subject: [PATCH] fix close code/reason issue (#34) * fix close code/reason issue * added code 1006 for abnormal closure --- ixwebsocket/IXWebSocketTransport.cpp | 28 ++++++++++++++++++++++------ ixwebsocket/IXWebSocketTransport.h | 15 ++++++++++++++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/ixwebsocket/IXWebSocketTransport.cpp b/ixwebsocket/IXWebSocketTransport.cpp index 67a6d6d8..c8980463 100644 --- a/ixwebsocket/IXWebSocketTransport.cpp +++ b/ixwebsocket/IXWebSocketTransport.cpp @@ -69,11 +69,16 @@ namespace ix const int WebSocketTransport::kDefaultPingTimeoutSecs(-1); const bool WebSocketTransport::kDefaultEnablePong(true); constexpr size_t WebSocketTransport::kChunkSize; + const int WebSocketTransport::kInternalErrorCode(1011); + const int WebSocketTransport::kAbnormalCloseCode(1006); + const std::string WebSocketTransport::kInternalErrorMessage("Internal error"); + const std::string WebSocketTransport::kAbnormalCloseMessage("Abnormal closure"); WebSocketTransport::WebSocketTransport() : _useMask(true), _readyState(CLOSED), - _closeCode(0), + _closeCode(kInternalErrorCode), + _closeReason(kInternalErrorMessage), _closeWireSize(0), _enablePerMessageDeflate(false), _requestInitCancellation(false), @@ -190,8 +195,8 @@ namespace ix { std::lock_guard lock(_closeDataMutex); _onCloseCallback(_closeCode, _closeReason, _closeWireSize); - _closeCode = 0; - _closeReason = std::string(); + _closeCode = kInternalErrorCode; + _closeReason = kInternalErrorMessage; _closeWireSize = 0; } @@ -284,6 +289,12 @@ namespace ix { _rxbuf.clear(); _socket->close(); + { + std::lock_guard lock(_closeDataMutex); + _closeCode = kAbnormalCloseCode; + _closeReason = kAbnormalCloseMessage; + _closeWireSize = 0; + } setReadyState(CLOSED); break; } @@ -526,8 +537,7 @@ namespace ix // Get the reason. std::string reason(_rxbuf.begin()+ws.header_size + 2, - _rxbuf.begin()+ws.header_size + 2 + (size_t) ws.N); - + _rxbuf.begin()+ws.header_size + (size_t) ws.N); close(code, reason, _rxbuf.size()); } @@ -843,7 +853,13 @@ namespace ix // See list of close events here: // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent - const std::string closure{(char)(code >> 8), (char)(code & 0xff)}; + + int codeLength = 2; + std::string closure{(char)(code >> 8), (char)(code & 0xff)}; + closure.resize(codeLength + reason.size()); + + // copy reason after code + closure.replace(codeLength, reason.size(), reason); bool compress = false; sendData(wsheader_type::CLOSE, closure, compress); diff --git a/ixwebsocket/IXWebSocketTransport.h b/ixwebsocket/IXWebSocketTransport.h index 8c2773e6..33e6a181 100644 --- a/ixwebsocket/IXWebSocketTransport.h +++ b/ixwebsocket/IXWebSocketTransport.h @@ -159,23 +159,36 @@ namespace ix // Used to cancel dns lookup + socket connect + http upgrade std::atomic _requestInitCancellation; + // Constants for dealing with closing conneections + static const int kInternalErrorCode; + static const int kAbnormalCloseCode; + const static std::string kInternalErrorMessage; + const static std::string kAbnormalCloseMessage; + // enable auto response to ping bool _enablePong; static const bool kDefaultEnablePong; - // Optional ping and ping timeout + // Optional ping and pong timeout int _pingIntervalSecs; int _pingTimeoutSecs; int _pingIntervalOrTimeoutGCDSecs; // if both ping interval and timeout are set (> 0), then use GCD of these value to wait for the lowest time + static const int kDefaultPingIntervalSecs; static const int kDefaultPingTimeoutSecs; const static std::string kPingMessage; + + // We record when ping are being sent so that we can know when to send the next one, periodically + // We also record when pong are being sent as a reply to pings, to close the connections + // if no pong were received sufficiently fast. mutable std::mutex _lastSendPingTimePointMutex; mutable std::mutex _lastReceivePongTimePointMutex; std::chrono::time_point _lastSendPingTimePoint; std::chrono::time_point _lastReceivePongTimePoint; + // If this function returns true, it is time to send a new ping bool pingIntervalExceeded(); + // No PONG data was received through the socket for longer than ping timeout delay bool pingTimeoutExceeded();