Better ping/pong support
This commit is contained in:
@ -177,8 +177,28 @@ namespace ix {
|
||||
|
||||
// 3. Dispatch the incoming messages
|
||||
_ws.dispatch(
|
||||
[this](const std::string& msg)
|
||||
[this](const std::string& msg,
|
||||
WebSocketTransport::MessageKind messageKind)
|
||||
{
|
||||
WebSocketMessageType webSocketMessageType;
|
||||
switch (messageKind)
|
||||
{
|
||||
case WebSocketTransport::MSG:
|
||||
{
|
||||
webSocketMessageType = WebSocket_MessageType_Message;
|
||||
} break;
|
||||
|
||||
case WebSocketTransport::PING:
|
||||
{
|
||||
webSocketMessageType = WebSocket_MessageType_Ping;
|
||||
} break;
|
||||
|
||||
case WebSocketTransport::PONG:
|
||||
{
|
||||
webSocketMessageType = WebSocket_MessageType_Pong;
|
||||
} break;
|
||||
}
|
||||
|
||||
_onMessageCallback(WebSocket_MessageType_Message, msg, WebSocketErrorInfo());
|
||||
|
||||
WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
|
||||
@ -210,6 +230,20 @@ namespace ix {
|
||||
}
|
||||
|
||||
bool WebSocket::send(const std::string& text)
|
||||
{
|
||||
return sendMessage(text, false);
|
||||
}
|
||||
|
||||
bool WebSocket::ping(const std::string& text)
|
||||
{
|
||||
// Standard limit ping message size
|
||||
constexpr size_t pingMaxPayloadSize = 125;
|
||||
if (text.size() > pingMaxPayloadSize) return false;
|
||||
|
||||
return sendMessage(text, true);
|
||||
}
|
||||
|
||||
bool WebSocket::sendMessage(const std::string& text, bool ping)
|
||||
{
|
||||
if (!isConnected()) return false;
|
||||
|
||||
@ -223,7 +257,15 @@ namespace ix {
|
||||
// incoming messages are arriving / there's data to be received.
|
||||
//
|
||||
std::lock_guard<std::mutex> lock(_writeMutex);
|
||||
_ws.sendBinary(text);
|
||||
|
||||
if (ping)
|
||||
{
|
||||
_ws.sendPing(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ws.sendBinary(text);
|
||||
}
|
||||
|
||||
WebSocket::invokeTrafficTrackerCallback(text.size(), false);
|
||||
|
||||
|
@ -32,7 +32,9 @@ namespace ix
|
||||
WebSocket_MessageType_Message = 0,
|
||||
WebSocket_MessageType_Open = 1,
|
||||
WebSocket_MessageType_Close = 2,
|
||||
WebSocket_MessageType_Error = 3
|
||||
WebSocket_MessageType_Error = 3,
|
||||
WebSocket_MessageType_Ping = 4,
|
||||
WebSocket_MessageType_Pong = 5
|
||||
};
|
||||
|
||||
struct WebSocketErrorInfo
|
||||
@ -56,6 +58,7 @@ namespace ix
|
||||
void start();
|
||||
void stop();
|
||||
bool send(const std::string& text);
|
||||
bool ping(const std::string& text);
|
||||
void close();
|
||||
|
||||
void setOnMessageCallback(const OnMessageCallback& callback);
|
||||
@ -70,6 +73,8 @@ namespace ix
|
||||
private:
|
||||
void run();
|
||||
|
||||
bool sendMessage(const std::string& text, bool ping);
|
||||
|
||||
WebSocketInitResult connect();
|
||||
bool isConnected() const;
|
||||
bool isClosing() const;
|
||||
|
@ -449,7 +449,7 @@ namespace ix {
|
||||
// fire callback with a string message
|
||||
std::string stringMessage(_receivedData.begin(),
|
||||
_receivedData.end());
|
||||
onMessageCallback(stringMessage);
|
||||
onMessageCallback(stringMessage, MSG);
|
||||
|
||||
_receivedData.clear();
|
||||
}
|
||||
@ -467,10 +467,27 @@ namespace ix {
|
||||
std::string pingData(_rxbuf.begin()+ws.header_size,
|
||||
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
||||
|
||||
// Reply back right away
|
||||
sendData(wsheader_type::PONG, pingData.size(),
|
||||
pingData.begin(), pingData.end());
|
||||
|
||||
onMessageCallback(pingData, PING);
|
||||
}
|
||||
else if (ws.opcode == wsheader_type::PONG)
|
||||
{
|
||||
if (ws.mask)
|
||||
{
|
||||
for (size_t j = 0; j != ws.N; ++j)
|
||||
{
|
||||
_rxbuf[j+ws.header_size] ^= ws.masking_key[j&0x3];
|
||||
}
|
||||
}
|
||||
|
||||
std::string pongData(_rxbuf.begin()+ws.header_size,
|
||||
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
||||
|
||||
onMessageCallback(pongData, PONG);
|
||||
}
|
||||
else if (ws.opcode == wsheader_type::PONG) { }
|
||||
else if (ws.opcode == wsheader_type::CLOSE) { close(); }
|
||||
else { close(); }
|
||||
|
||||
@ -556,10 +573,9 @@ namespace ix {
|
||||
sendOnSocket();
|
||||
}
|
||||
|
||||
void WebSocketTransport::sendPing()
|
||||
void WebSocketTransport::sendPing(const std::string& message)
|
||||
{
|
||||
std::string empty;
|
||||
sendData(wsheader_type::PING, empty.size(), empty.begin(), empty.end());
|
||||
sendData(wsheader_type::PING, message.size(), message.begin(), message.end());
|
||||
}
|
||||
|
||||
void WebSocketTransport::sendBinary(const std::string& message)
|
||||
|
@ -54,7 +54,15 @@ namespace ix
|
||||
OPEN
|
||||
};
|
||||
|
||||
using OnMessageCallback = std::function<void(const std::string&)>;
|
||||
enum MessageKind
|
||||
{
|
||||
MSG,
|
||||
PING,
|
||||
PONG
|
||||
};
|
||||
|
||||
using OnMessageCallback = std::function<void(const std::string&,
|
||||
MessageKind)>;
|
||||
using OnStateChangeCallback = std::function<void(ReadyStateValues)>;
|
||||
|
||||
WebSocketTransport();
|
||||
@ -67,7 +75,7 @@ namespace ix
|
||||
void send(const std::string& message);
|
||||
void sendBinary(const std::string& message);
|
||||
void sendBinary(const std::vector<uint8_t>& message);
|
||||
void sendPing();
|
||||
void sendPing(const std::string& message);
|
||||
void close();
|
||||
ReadyStateValues getReadyState() const;
|
||||
void setReadyState(ReadyStateValues readyStateValue);
|
||||
|
Reference in New Issue
Block a user