From aa2ca198957735c353ca046365a4519f03c45b88 Mon Sep 17 00:00:00 2001 From: YuHuanTin <51024916+YuHuanTin@users.noreply.github.com> Date: Fri, 24 Feb 2023 00:29:07 +0800 Subject: [PATCH] Added support for setting custom ping messages with support for any 'ping' message type (binary ping message, text ping message) (#438) * Added support for setting custom ping messages with support for any 'ping' message type (binary ping message, text ping message) * Add default value --------- Co-authored-by: YuHuanTin <2@> --- ixwebsocket/IXWebSocket.cpp | 20 ++++++++-- ixwebsocket/IXWebSocket.h | 7 +++- ixwebsocket/IXWebSocketTransport.cpp | 56 ++++++++++++++++++++++++---- ixwebsocket/IXWebSocketTransport.h | 11 +++++- 4 files changed, 80 insertions(+), 14 deletions(-) diff --git a/ixwebsocket/IXWebSocket.cpp b/ixwebsocket/IXWebSocket.cpp index 5c3ec9ad..86b6c3ee 100644 --- a/ixwebsocket/IXWebSocket.cpp +++ b/ixwebsocket/IXWebSocket.cpp @@ -39,6 +39,7 @@ namespace ix , _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs) , _enablePong(kDefaultEnablePong) , _pingIntervalSecs(kDefaultPingIntervalSecs) + , _pingType(SendMessageKind::Ping) { _ws.setOnCloseCallback( [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) @@ -101,6 +102,17 @@ namespace ix return _perMessageDeflateOptions; } + void WebSocket::setPingMessage(const std::string& sendMessage, SendMessageKind pingType) + { + std::lock_guard lock(_configMutex); + _pingMessage = sendMessage; + _ws.setPingMessage(_pingMessage, pingType); + } + const std::string WebSocket::getPingMessage() const + { + std::lock_guard lock(_configMutex); + return _pingMessage; + } void WebSocket::setPingInterval(int pingIntervalSecs) { std::lock_guard lock(_configMutex); @@ -233,7 +245,7 @@ namespace ix if (_pingIntervalSecs > 0) { // Send a heart beat right away - _ws.sendHeartBeat(); + _ws.sendHeartBeat(_pingType); } return status; @@ -268,7 +280,7 @@ namespace ix if (_pingIntervalSecs > 0) { // Send a heart beat right away - _ws.sendHeartBeat(); + _ws.sendHeartBeat(_pingType); } return status; @@ -506,13 +518,13 @@ namespace ix return sendMessage(text, SendMessageKind::Text, onProgressCallback); } - WebSocketSendInfo WebSocket::ping(const std::string& text) + WebSocketSendInfo WebSocket::ping(const std::string& text, SendMessageKind pingType) { // Standard limit ping message size constexpr size_t pingMaxPayloadSize = 125; if (text.size() > pingMaxPayloadSize) return WebSocketSendInfo(false); - return sendMessage(text, SendMessageKind::Ping); + return sendMessage(text, pingType); } WebSocketSendInfo WebSocket::sendMessage(const IXWebSocketSendData& message, diff --git a/ixwebsocket/IXWebSocket.h b/ixwebsocket/IXWebSocket.h index 84ef3b85..70868bba 100644 --- a/ixwebsocket/IXWebSocket.h +++ b/ixwebsocket/IXWebSocket.h @@ -53,6 +53,8 @@ namespace ix void setPerMessageDeflateOptions( const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); void setTLSOptions(const SocketTLSOptions& socketTLSOptions); + void setPingMessage(const std::string& sendMessage, + SendMessageKind pingType = SendMessageKind::Ping); void setPingInterval(int pingIntervalSecs); void enablePong(); void disablePong(); @@ -88,7 +90,7 @@ namespace ix const OnProgressCallback& onProgressCallback = nullptr); WebSocketSendInfo sendText(const std::string& text, const OnProgressCallback& onProgressCallback = nullptr); - WebSocketSendInfo ping(const std::string& text); + WebSocketSendInfo ping(const std::string& text,SendMessageKind pingType = SendMessageKind::Ping); void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage); @@ -103,6 +105,7 @@ namespace ix const std::string getUrl() const; const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const; + const std::string getPingMessage() const; int getPingInterval() const; size_t bufferedAmount() const; @@ -170,6 +173,8 @@ namespace ix // Optional ping and pong timeout int _pingIntervalSecs; int _pingTimeoutSecs; + std::string _pingMessage; + SendMessageKind _pingType; static const int kDefaultPingIntervalSecs; static const int kDefaultPingTimeoutSecs; diff --git a/ixwebsocket/IXWebSocketTransport.cpp b/ixwebsocket/IXWebSocketTransport.cpp index f4d89e7e..b699a399 100644 --- a/ixwebsocket/IXWebSocketTransport.cpp +++ b/ixwebsocket/IXWebSocketTransport.cpp @@ -54,7 +54,6 @@ namespace ix { - const std::string WebSocketTransport::kPingMessage("ixwebsocket::heartbeat"); const int WebSocketTransport::kDefaultPingIntervalSecs(-1); const bool WebSocketTransport::kDefaultEnablePong(true); const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300); @@ -73,6 +72,9 @@ namespace ix , _closingTimePoint(std::chrono::steady_clock::now()) , _enablePong(kDefaultEnablePong) , _pingIntervalSecs(kDefaultPingIntervalSecs) + , _setCustomMessage(false) + , _kPingMessage("ixwebsocket::heartbeat") + , _pingType(SendMessageKind::Ping) , _pongReceived(false) , _pingCount(0) , _lastSendPingTimePoint(std::chrono::steady_clock::now()) @@ -250,13 +252,51 @@ namespace ix return now - _lastSendPingTimePoint > std::chrono::seconds(_pingIntervalSecs); } - WebSocketSendInfo WebSocketTransport::sendHeartBeat() + void WebSocketTransport::setPingMessage(const std::string& message, SendMessageKind pingType) + { + _setCustomMessage = true; + _kPingMessage = message; + _pingType = pingType; + } + + WebSocketSendInfo WebSocketTransport::sendHeartBeat(SendMessageKind pingMessage) { _pongReceived = false; std::stringstream ss; - ss << kPingMessage << "::" << _pingIntervalSecs << "s" - << "::" << _pingCount++; - return sendPing(ss.str()); + + ss << _kPingMessage; + if (!_setCustomMessage) + { + ss << "::" << _pingIntervalSecs << "s" + << "::" << _pingCount++; + } + if (pingMessage == SendMessageKind::Ping) + { + return sendPing(ss.str()); + } + else if (pingMessage == SendMessageKind::Binary) + { + WebSocketSendInfo info = sendBinary(ss.str(), nullptr); + if (info.success) + { + std::lock_guard lck(_lastSendPingTimePointMutex); + _lastSendPingTimePoint = std::chrono::steady_clock::now(); + } + return info; + } + else if (pingMessage == SendMessageKind::Text) + { + WebSocketSendInfo info = sendText(ss.str(), nullptr); + if (info.success) + { + std::lock_guard lck(_lastSendPingTimePointMutex); + _lastSendPingTimePoint = std::chrono::steady_clock::now(); + } + return info; + } + + // unknow type ping message + return {}; } bool WebSocketTransport::closingDelayExceeded() @@ -272,7 +312,9 @@ namespace ix { if (pingIntervalExceeded()) { - if (!_pongReceived) + // If it is not a 'ping' message of ping type, there is no need to judge whether + // pong will receive it + if (_pingType == SendMessageKind::Ping && !_pongReceived) { // ping response (PONG) exceeds the maximum delay, close the connection close(WebSocketCloseConstants::kInternalErrorCode, @@ -280,7 +322,7 @@ namespace ix } else { - sendHeartBeat(); + sendHeartBeat(_pingType); } } } diff --git a/ixwebsocket/IXWebSocketTransport.h b/ixwebsocket/IXWebSocketTransport.h index 7e906daa..8280cfe4 100644 --- a/ixwebsocket/IXWebSocketTransport.h +++ b/ixwebsocket/IXWebSocketTransport.h @@ -109,8 +109,12 @@ namespace ix void dispatch(PollResult pollResult, const OnMessageCallback& onMessageCallback); size_t bufferedAmount() const; + // set ping heartbeat message + void setPingMessage(const std::string& message, SendMessageKind pingType); + // internal - WebSocketSendInfo sendHeartBeat(); + // send any type of ping packet, not only 'ping' type + WebSocketSendInfo sendHeartBeat(SendMessageKind pingType); private: std::string _url; @@ -215,7 +219,10 @@ namespace ix std::atomic _pongReceived; static const int kDefaultPingIntervalSecs; - static const std::string kPingMessage; + + bool _setCustomMessage; + std::string _kPingMessage; + SendMessageKind _pingType; std::atomic _pingCount; // We record when ping are being sent so that we can know when to send the next one