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@>
This commit is contained in:
		@@ -39,6 +39,7 @@ namespace ix
 | 
				
			|||||||
        , _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs)
 | 
					        , _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs)
 | 
				
			||||||
        , _enablePong(kDefaultEnablePong)
 | 
					        , _enablePong(kDefaultEnablePong)
 | 
				
			||||||
        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
					        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
				
			||||||
 | 
					        , _pingType(SendMessageKind::Ping)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _ws.setOnCloseCallback(
 | 
					        _ws.setOnCloseCallback(
 | 
				
			||||||
            [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote)
 | 
					            [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote)
 | 
				
			||||||
@@ -101,6 +102,17 @@ namespace ix
 | 
				
			|||||||
        return _perMessageDeflateOptions;
 | 
					        return _perMessageDeflateOptions;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WebSocket::setPingMessage(const std::string& sendMessage, SendMessageKind pingType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
 | 
					        _pingMessage = sendMessage;
 | 
				
			||||||
 | 
					        _ws.setPingMessage(_pingMessage, pingType);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const std::string WebSocket::getPingMessage() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
 | 
					        return _pingMessage;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    void WebSocket::setPingInterval(int pingIntervalSecs)
 | 
					    void WebSocket::setPingInterval(int pingIntervalSecs)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_configMutex);
 | 
					        std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
@@ -233,7 +245,7 @@ namespace ix
 | 
				
			|||||||
        if (_pingIntervalSecs > 0)
 | 
					        if (_pingIntervalSecs > 0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Send a heart beat right away
 | 
					            // Send a heart beat right away
 | 
				
			||||||
            _ws.sendHeartBeat();
 | 
					            _ws.sendHeartBeat(_pingType);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return status;
 | 
					        return status;
 | 
				
			||||||
@@ -268,7 +280,7 @@ namespace ix
 | 
				
			|||||||
        if (_pingIntervalSecs > 0)
 | 
					        if (_pingIntervalSecs > 0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Send a heart beat right away
 | 
					            // Send a heart beat right away
 | 
				
			||||||
            _ws.sendHeartBeat();
 | 
					            _ws.sendHeartBeat(_pingType);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return status;
 | 
					        return status;
 | 
				
			||||||
@@ -506,13 +518,13 @@ namespace ix
 | 
				
			|||||||
        return sendMessage(text, SendMessageKind::Text, onProgressCallback);
 | 
					        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
 | 
					        // Standard limit ping message size
 | 
				
			||||||
        constexpr size_t pingMaxPayloadSize = 125;
 | 
					        constexpr size_t pingMaxPayloadSize = 125;
 | 
				
			||||||
        if (text.size() > pingMaxPayloadSize) return WebSocketSendInfo(false);
 | 
					        if (text.size() > pingMaxPayloadSize) return WebSocketSendInfo(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return sendMessage(text, SendMessageKind::Ping);
 | 
					        return sendMessage(text, pingType);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketSendInfo WebSocket::sendMessage(const IXWebSocketSendData& message,
 | 
					    WebSocketSendInfo WebSocket::sendMessage(const IXWebSocketSendData& message,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,8 @@ namespace ix
 | 
				
			|||||||
        void setPerMessageDeflateOptions(
 | 
					        void setPerMessageDeflateOptions(
 | 
				
			||||||
            const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
					            const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
				
			||||||
        void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
 | 
					        void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
 | 
				
			||||||
 | 
					        void setPingMessage(const std::string& sendMessage,
 | 
				
			||||||
 | 
					                            SendMessageKind pingType = SendMessageKind::Ping);
 | 
				
			||||||
        void setPingInterval(int pingIntervalSecs);
 | 
					        void setPingInterval(int pingIntervalSecs);
 | 
				
			||||||
        void enablePong();
 | 
					        void enablePong();
 | 
				
			||||||
        void disablePong();
 | 
					        void disablePong();
 | 
				
			||||||
@@ -88,7 +90,7 @@ namespace ix
 | 
				
			|||||||
                                       const OnProgressCallback& onProgressCallback = nullptr);
 | 
					                                       const OnProgressCallback& onProgressCallback = nullptr);
 | 
				
			||||||
        WebSocketSendInfo sendText(const std::string& text,
 | 
					        WebSocketSendInfo sendText(const std::string& text,
 | 
				
			||||||
                                   const OnProgressCallback& onProgressCallback = nullptr);
 | 
					                                   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,
 | 
					        void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode,
 | 
				
			||||||
                   const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
 | 
					                   const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
 | 
				
			||||||
@@ -103,6 +105,7 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const std::string getUrl() const;
 | 
					        const std::string getUrl() const;
 | 
				
			||||||
        const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const;
 | 
					        const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const;
 | 
				
			||||||
 | 
					        const std::string getPingMessage() const;
 | 
				
			||||||
        int getPingInterval() const;
 | 
					        int getPingInterval() const;
 | 
				
			||||||
        size_t bufferedAmount() const;
 | 
					        size_t bufferedAmount() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -170,6 +173,8 @@ namespace ix
 | 
				
			|||||||
        // Optional ping and pong timeout
 | 
					        // Optional ping and pong timeout
 | 
				
			||||||
        int _pingIntervalSecs;
 | 
					        int _pingIntervalSecs;
 | 
				
			||||||
        int _pingTimeoutSecs;
 | 
					        int _pingTimeoutSecs;
 | 
				
			||||||
 | 
					        std::string _pingMessage;
 | 
				
			||||||
 | 
					        SendMessageKind _pingType;
 | 
				
			||||||
        static const int kDefaultPingIntervalSecs;
 | 
					        static const int kDefaultPingIntervalSecs;
 | 
				
			||||||
        static const int kDefaultPingTimeoutSecs;
 | 
					        static const int kDefaultPingTimeoutSecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,7 +54,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const std::string WebSocketTransport::kPingMessage("ixwebsocket::heartbeat");
 | 
					 | 
				
			||||||
    const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
 | 
					    const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
 | 
				
			||||||
    const bool WebSocketTransport::kDefaultEnablePong(true);
 | 
					    const bool WebSocketTransport::kDefaultEnablePong(true);
 | 
				
			||||||
    const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300);
 | 
					    const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300);
 | 
				
			||||||
@@ -73,6 +72,9 @@ namespace ix
 | 
				
			|||||||
        , _closingTimePoint(std::chrono::steady_clock::now())
 | 
					        , _closingTimePoint(std::chrono::steady_clock::now())
 | 
				
			||||||
        , _enablePong(kDefaultEnablePong)
 | 
					        , _enablePong(kDefaultEnablePong)
 | 
				
			||||||
        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
					        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
				
			||||||
 | 
					        , _setCustomMessage(false)
 | 
				
			||||||
 | 
					        , _kPingMessage("ixwebsocket::heartbeat")
 | 
				
			||||||
 | 
					        , _pingType(SendMessageKind::Ping)
 | 
				
			||||||
        , _pongReceived(false)
 | 
					        , _pongReceived(false)
 | 
				
			||||||
        , _pingCount(0)
 | 
					        , _pingCount(0)
 | 
				
			||||||
        , _lastSendPingTimePoint(std::chrono::steady_clock::now())
 | 
					        , _lastSendPingTimePoint(std::chrono::steady_clock::now())
 | 
				
			||||||
@@ -250,13 +252,51 @@ namespace ix
 | 
				
			|||||||
        return now - _lastSendPingTimePoint > std::chrono::seconds(_pingIntervalSecs);
 | 
					        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;
 | 
					        _pongReceived = false;
 | 
				
			||||||
        std::stringstream ss;
 | 
					        std::stringstream ss;
 | 
				
			||||||
        ss << kPingMessage << "::" << _pingIntervalSecs << "s"
 | 
					
 | 
				
			||||||
           << "::" << _pingCount++;
 | 
					        ss << _kPingMessage;
 | 
				
			||||||
        return sendPing(ss.str());
 | 
					        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<std::mutex> 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<std::mutex> lck(_lastSendPingTimePointMutex);
 | 
				
			||||||
 | 
					                _lastSendPingTimePoint = std::chrono::steady_clock::now();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return info;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // unknow type ping message
 | 
				
			||||||
 | 
					        return {};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool WebSocketTransport::closingDelayExceeded()
 | 
					    bool WebSocketTransport::closingDelayExceeded()
 | 
				
			||||||
@@ -272,7 +312,9 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (pingIntervalExceeded())
 | 
					            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
 | 
					                    // ping response (PONG) exceeds the maximum delay, close the connection
 | 
				
			||||||
                    close(WebSocketCloseConstants::kInternalErrorCode,
 | 
					                    close(WebSocketCloseConstants::kInternalErrorCode,
 | 
				
			||||||
@@ -280,7 +322,7 @@ namespace ix
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    sendHeartBeat();
 | 
					                    sendHeartBeat(_pingType);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,8 +109,12 @@ namespace ix
 | 
				
			|||||||
        void dispatch(PollResult pollResult, const OnMessageCallback& onMessageCallback);
 | 
					        void dispatch(PollResult pollResult, const OnMessageCallback& onMessageCallback);
 | 
				
			||||||
        size_t bufferedAmount() const;
 | 
					        size_t bufferedAmount() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // set ping heartbeat message
 | 
				
			||||||
 | 
					        void setPingMessage(const std::string& message, SendMessageKind pingType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // internal
 | 
					        // internal
 | 
				
			||||||
        WebSocketSendInfo sendHeartBeat();
 | 
					        // send any type of ping packet, not only 'ping' type
 | 
				
			||||||
 | 
					        WebSocketSendInfo sendHeartBeat(SendMessageKind pingType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        std::string _url;
 | 
					        std::string _url;
 | 
				
			||||||
@@ -215,7 +219,10 @@ namespace ix
 | 
				
			|||||||
        std::atomic<bool> _pongReceived;
 | 
					        std::atomic<bool> _pongReceived;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static const int kDefaultPingIntervalSecs;
 | 
					        static const int kDefaultPingIntervalSecs;
 | 
				
			||||||
        static const std::string kPingMessage;
 | 
					
 | 
				
			||||||
 | 
					        bool _setCustomMessage;
 | 
				
			||||||
 | 
					        std::string _kPingMessage;
 | 
				
			||||||
 | 
					        SendMessageKind _pingType;
 | 
				
			||||||
        std::atomic<uint64_t> _pingCount;
 | 
					        std::atomic<uint64_t> _pingCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // We record when ping are being sent so that we can know when to send the next one
 | 
					        // We record when ping are being sent so that we can know when to send the next one
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user