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:
YuHuanTin 2023-02-24 00:29:07 +08:00 committed by GitHub
parent 6cc21f3658
commit aa2ca19895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 14 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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);
} }
} }
} }

View File

@ -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