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)
, _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<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)
{
std::lock_guard<std::mutex> 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,

View File

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

View File

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

View File

@ -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<bool> _pongReceived;
static const int kDefaultPingIntervalSecs;
static const std::string kPingMessage;
bool _setCustomMessage;
std::string _kPingMessage;
SendMessageKind _pingType;
std::atomic<uint64_t> _pingCount;
// We record when ping are being sent so that we can know when to send the next one