capture an error code and a reason when the server closes the connection
This commit is contained in:
parent
390044b716
commit
a8dfd640a7
16
README.md
16
README.md
@ -25,7 +25,10 @@ webSocket.configure(url);
|
|||||||
|
|
||||||
// Setup a callback to be fired when a message or an event (open, close, error) is received
|
// Setup a callback to be fired when a message or an event (open, close, error) is received
|
||||||
webSocket.setOnMessageCallback(
|
webSocket.setOnMessageCallback(
|
||||||
[](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error)
|
[](ix::WebSocketMessageType messageType,
|
||||||
|
const std::string& str,
|
||||||
|
const ix::WebSocketErrorInfo& error,
|
||||||
|
const ix::CloseInfo& closeInfo)
|
||||||
{
|
{
|
||||||
if (messageType == ix::WebSocket_MessageType_Message)
|
if (messageType == ix::WebSocket_MessageType_Message)
|
||||||
{
|
{
|
||||||
@ -124,7 +127,7 @@ The onMessage event will be fired when the connection is opened or closed. This
|
|||||||
|
|
||||||
```
|
```
|
||||||
webSocket.setOnMessageCallback(
|
webSocket.setOnMessageCallback(
|
||||||
[this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error)
|
[this](ix::WebSocketMessageType messageType, const std::string& str, const ix::WebSocketErrorInfo& error, const ix::CloseInfo closeInfo&)
|
||||||
{
|
{
|
||||||
if (messageType == ix::WebSocket_MessageType_Open)
|
if (messageType == ix::WebSocket_MessageType_Open)
|
||||||
{
|
{
|
||||||
@ -133,6 +136,11 @@ webSocket.setOnMessageCallback(
|
|||||||
else if (messageType == ix::WebSocket_MessageType_Close)
|
else if (messageType == ix::WebSocket_MessageType_Close)
|
||||||
{
|
{
|
||||||
puts("disconnected");
|
puts("disconnected");
|
||||||
|
|
||||||
|
// The server can send an explicit code and reason for closing.
|
||||||
|
// This data can be accessed through the closeInfo object.
|
||||||
|
std::cout << closeInfo.code << std::endl;
|
||||||
|
std::cout << closeInfo.reason << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -144,7 +152,7 @@ A message will be fired when there is an error with the connection. The message
|
|||||||
|
|
||||||
```
|
```
|
||||||
webSocket.setOnMessageCallback(
|
webSocket.setOnMessageCallback(
|
||||||
[this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error)
|
[this](ix::WebSocketMessageType messageType, const std::string& str, const ix::WebSocketErrorInfo& error, const ix::CloseInfo& closeInfo)
|
||||||
{
|
{
|
||||||
if (messageType == ix::WebSocket_MessageType_Error)
|
if (messageType == ix::WebSocket_MessageType_Error)
|
||||||
{
|
{
|
||||||
@ -179,7 +187,7 @@ Ping/pong messages are used to implement keep-alive. 2 message types exists to i
|
|||||||
|
|
||||||
```
|
```
|
||||||
webSocket.setOnMessageCallback(
|
webSocket.setOnMessageCallback(
|
||||||
[this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error)
|
[this](ix::WebSocketMessageType messageType, const std::string& str, const ix::WebSocketErrorInfo& error, const ix::CloseInfo& closeInfo)
|
||||||
{
|
{
|
||||||
if (messageType == ix::WebSocket_MessageType_Ping ||
|
if (messageType == ix::WebSocket_MessageType_Ping ||
|
||||||
messageType == ix::WebSocket_MessageType_Pong)
|
messageType == ix::WebSocket_MessageType_Pong)
|
||||||
|
@ -83,7 +83,10 @@ namespace
|
|||||||
log(std::string("Connecting to url: ") + url);
|
log(std::string("Connecting to url: ") + url);
|
||||||
|
|
||||||
_webSocket.setOnMessageCallback(
|
_webSocket.setOnMessageCallback(
|
||||||
[this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error)
|
[this](ix::WebSocketMessageType messageType,
|
||||||
|
const std::string& str,
|
||||||
|
const ix::WebSocketErrorInfo& error,
|
||||||
|
const ix::CloseInfo& closeInfo)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (messageType == ix::WebSocket_MessageType_Open)
|
if (messageType == ix::WebSocket_MessageType_Open)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* ws_connect.cpp
|
* ping_pong.cpp
|
||||||
* Author: Benjamin Sergeant
|
* Author: Benjamin Sergeant
|
||||||
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
@ -28,6 +28,7 @@ namespace
|
|||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
void ping(const std::string& text);
|
void ping(const std::string& text);
|
||||||
|
void send(const std::string& text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _url;
|
std::string _url;
|
||||||
@ -53,32 +54,39 @@ namespace
|
|||||||
log(std::string("Connecting to url: ") + _url);
|
log(std::string("Connecting to url: ") + _url);
|
||||||
|
|
||||||
_webSocket.setOnMessageCallback(
|
_webSocket.setOnMessageCallback(
|
||||||
[this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error)
|
[this](ix::WebSocketMessageType messageType,
|
||||||
|
const std::string& str,
|
||||||
|
const ix::WebSocketErrorInfo& error,
|
||||||
|
const ix::CloseInfo& closeInfo)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (messageType == ix::WebSocket_MessageType_Open)
|
if (messageType == ix::WebSocket_MessageType_Open)
|
||||||
{
|
{
|
||||||
log("ws_connect: connected");
|
log("ping_pong: connected");
|
||||||
}
|
}
|
||||||
else if (messageType == ix::WebSocket_MessageType_Close)
|
else if (messageType == ix::WebSocket_MessageType_Close)
|
||||||
{
|
{
|
||||||
log("ws_connect: disconnected");
|
ss << "ping_pong: disconnected:"
|
||||||
|
<< " code " << closeInfo.code
|
||||||
|
<< " reason " << closeInfo.reason
|
||||||
|
<< str;
|
||||||
|
log(ss.str());
|
||||||
}
|
}
|
||||||
else if (messageType == ix::WebSocket_MessageType_Message)
|
else if (messageType == ix::WebSocket_MessageType_Message)
|
||||||
{
|
{
|
||||||
ss << "ws_connect: received message: "
|
ss << "ping_pong: received message: "
|
||||||
<< str;
|
<< str;
|
||||||
log(ss.str());
|
log(ss.str());
|
||||||
}
|
}
|
||||||
else if (messageType == ix::WebSocket_MessageType_Ping)
|
else if (messageType == ix::WebSocket_MessageType_Ping)
|
||||||
{
|
{
|
||||||
ss << "ws_connect: received ping message: "
|
ss << "ping_pong: received ping message: "
|
||||||
<< str;
|
<< str;
|
||||||
log(ss.str());
|
log(ss.str());
|
||||||
}
|
}
|
||||||
else if (messageType == ix::WebSocket_MessageType_Pong)
|
else if (messageType == ix::WebSocket_MessageType_Pong)
|
||||||
{
|
{
|
||||||
ss << "ws_connect: received pong message: "
|
ss << "ping_pong: received pong message: "
|
||||||
<< str;
|
<< str;
|
||||||
log(ss.str());
|
log(ss.str());
|
||||||
}
|
}
|
||||||
@ -109,6 +117,11 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocketPingPong::send(const std::string& text)
|
||||||
|
{
|
||||||
|
_webSocket.send(text);
|
||||||
|
}
|
||||||
|
|
||||||
void interactiveMain(const std::string& url)
|
void interactiveMain(const std::string& url)
|
||||||
{
|
{
|
||||||
std::cout << "Type Ctrl-D to exit prompt..." << std::endl;
|
std::cout << "Type Ctrl-D to exit prompt..." << std::endl;
|
||||||
@ -126,7 +139,14 @@ namespace
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
webSocketPingPong.ping(text);
|
if (text == "/close")
|
||||||
|
{
|
||||||
|
webSocketPingPong.send(text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
webSocketPingPong.ping(text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
import websockets
|
import websockets
|
||||||
|
|
||||||
@ -8,6 +9,13 @@ async def echo(websocket, path):
|
|||||||
print(message)
|
print(message)
|
||||||
await websocket.send(message)
|
await websocket.send(message)
|
||||||
|
|
||||||
|
if os.getenv('TEST_CLOSE'):
|
||||||
|
print('Closing')
|
||||||
|
# breakpoint()
|
||||||
|
await websocket.close(1001, 'close message')
|
||||||
|
# await websocket.close()
|
||||||
|
break
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.get_event_loop().run_until_complete(
|
||||||
websockets.serve(echo, 'localhost', 5678))
|
websockets.serve(echo, 'localhost', 5678))
|
||||||
asyncio.get_event_loop().run_forever()
|
asyncio.get_event_loop().run_forever()
|
||||||
|
@ -53,7 +53,10 @@ namespace
|
|||||||
log(std::string("Connecting to url: ") + _url);
|
log(std::string("Connecting to url: ") + _url);
|
||||||
|
|
||||||
_webSocket.setOnMessageCallback(
|
_webSocket.setOnMessageCallback(
|
||||||
[this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error)
|
[this](ix::WebSocketMessageType messageType,
|
||||||
|
const std::string& str,
|
||||||
|
const ix::WebSocketErrorInfo& error,
|
||||||
|
const ix::CloseInfo& closeInfo)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (messageType == ix::WebSocket_MessageType_Open)
|
if (messageType == ix::WebSocket_MessageType_Open)
|
||||||
|
@ -10,9 +10,8 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
// FIXME: put this in a shared location, and use it in
|
|
||||||
uint64_t calculateRetryWaitMilliseconds(uint64_t retry_count)
|
uint64_t calculateRetryWaitMilliseconds(uint64_t retry_count)
|
||||||
{
|
{
|
||||||
// This will overflow quite fast for large value of retry_count
|
// This will overflow quite fast for large value of retry_count
|
||||||
@ -24,7 +23,6 @@ namespace {
|
|||||||
uint64_t tenSeconds = 10 * 1000;
|
uint64_t tenSeconds = 10 * 1000;
|
||||||
return (wait_time > tenSeconds || retry_count > 10) ? tenSeconds : wait_time;
|
return (wait_time > tenSeconds || retry_count > 10) ? tenSeconds : wait_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ix {
|
namespace ix {
|
||||||
@ -32,7 +30,6 @@ namespace ix {
|
|||||||
OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr;
|
OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr;
|
||||||
|
|
||||||
WebSocket::WebSocket() :
|
WebSocket::WebSocket() :
|
||||||
_verbose(false),
|
|
||||||
_onMessageCallback(OnMessageCallback()),
|
_onMessageCallback(OnMessageCallback()),
|
||||||
_stop(false),
|
_stop(false),
|
||||||
_automaticReconnection(true)
|
_automaticReconnection(true)
|
||||||
@ -83,20 +80,11 @@ namespace ix {
|
|||||||
_ws.configure(_url);
|
_ws.configure(_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ws.setOnStateChangeCallback(
|
_ws.setOnCloseCallback(
|
||||||
[this](WebSocketTransport::ReadyStateValues readyStateValue)
|
[this](uint16_t code, const std::string& reason)
|
||||||
{
|
{
|
||||||
if (readyStateValue == WebSocketTransport::CLOSED)
|
_onMessageCallback(WebSocket_MessageType_Close, "",
|
||||||
{
|
WebSocketErrorInfo(), CloseInfo(code, reason));
|
||||||
_onMessageCallback(WebSocket_MessageType_Close, "", WebSocketErrorInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_verbose)
|
|
||||||
{
|
|
||||||
std::cout << "connection state changed -> "
|
|
||||||
<< readyStateToString(getReadyState())
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -106,7 +94,8 @@ namespace ix {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMessageCallback(WebSocket_MessageType_Open, "", WebSocketErrorInfo());
|
_onMessageCallback(WebSocket_MessageType_Open, "",
|
||||||
|
WebSocketErrorInfo(), CloseInfo());
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,9 +139,8 @@ namespace ix {
|
|||||||
connectErr.wait_time = duration.count();
|
connectErr.wait_time = duration.count();
|
||||||
connectErr.reason = status.errorStr;
|
connectErr.reason = status.errorStr;
|
||||||
connectErr.http_status = status.http_status;
|
connectErr.http_status = status.http_status;
|
||||||
_onMessageCallback(WebSocket_MessageType_Error, "", connectErr);
|
_onMessageCallback(WebSocket_MessageType_Error, "",
|
||||||
|
connectErr, CloseInfo());
|
||||||
if (_verbose) std::cout << "Sleeping for " << duration.count() << "ms" << std::endl;
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(duration);
|
std::this_thread::sleep_for(duration);
|
||||||
}
|
}
|
||||||
@ -199,7 +187,8 @@ namespace ix {
|
|||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMessageCallback(webSocketMessageType, msg, WebSocketErrorInfo());
|
_onMessageCallback(webSocketMessageType, msg,
|
||||||
|
WebSocketErrorInfo(), CloseInfo());
|
||||||
|
|
||||||
WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
|
WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
|
||||||
});
|
});
|
||||||
|
@ -45,7 +45,28 @@ namespace ix
|
|||||||
std::string reason;
|
std::string reason;
|
||||||
};
|
};
|
||||||
|
|
||||||
using OnMessageCallback = std::function<void(WebSocketMessageType, const std::string&, const WebSocketErrorInfo)>;
|
struct CloseInfo
|
||||||
|
{
|
||||||
|
uint16_t code;
|
||||||
|
std::string reason;
|
||||||
|
|
||||||
|
CloseInfo(uint64_t c, const std::string& r)
|
||||||
|
{
|
||||||
|
code = c;
|
||||||
|
reason = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseInfo()
|
||||||
|
{
|
||||||
|
code = 0;
|
||||||
|
reason = "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using OnMessageCallback = std::function<void(WebSocketMessageType,
|
||||||
|
const std::string&,
|
||||||
|
const WebSocketErrorInfo,
|
||||||
|
const CloseInfo)>;
|
||||||
using OnTrafficTrackerCallback = std::function<void(size_t size, bool incoming)>;
|
using OnTrafficTrackerCallback = std::function<void(size_t size, bool incoming)>;
|
||||||
|
|
||||||
class WebSocket
|
class WebSocket
|
||||||
@ -65,8 +86,6 @@ namespace ix
|
|||||||
static void setTrafficTrackerCallback(const OnTrafficTrackerCallback& callback);
|
static void setTrafficTrackerCallback(const OnTrafficTrackerCallback& callback);
|
||||||
static void resetTrafficTrackerCallback();
|
static void resetTrafficTrackerCallback();
|
||||||
|
|
||||||
void setVerbose(bool verbose) { _verbose = verbose; }
|
|
||||||
|
|
||||||
const std::string& getUrl() const;
|
const std::string& getUrl() const;
|
||||||
ReadyState getReadyState() const;
|
ReadyState getReadyState() const;
|
||||||
|
|
||||||
@ -86,7 +105,6 @@ namespace ix
|
|||||||
|
|
||||||
std::string _url;
|
std::string _url;
|
||||||
mutable std::mutex _urlMutex;
|
mutable std::mutex _urlMutex;
|
||||||
bool _verbose;
|
|
||||||
|
|
||||||
OnMessageCallback _onMessageCallback;
|
OnMessageCallback _onMessageCallback;
|
||||||
static OnTrafficTrackerCallback _onTrafficTrackerCallback;
|
static OnTrafficTrackerCallback _onTrafficTrackerCallback;
|
||||||
|
@ -255,13 +255,20 @@ namespace ix {
|
|||||||
|
|
||||||
void WebSocketTransport::setReadyState(ReadyStateValues readyStateValue)
|
void WebSocketTransport::setReadyState(ReadyStateValues readyStateValue)
|
||||||
{
|
{
|
||||||
|
if (readyStateValue == CLOSED)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_closeDataMutex);
|
||||||
|
_onCloseCallback(_closeCode, _closeReason);
|
||||||
|
_closeCode = 0;
|
||||||
|
_closeReason = std::string();
|
||||||
|
}
|
||||||
|
|
||||||
_readyState = readyStateValue;
|
_readyState = readyStateValue;
|
||||||
_onStateChangeCallback(readyStateValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketTransport::setOnStateChangeCallback(const OnStateChangeCallback& onStateChangeCallback)
|
void WebSocketTransport::setOnCloseCallback(const OnCloseCallback& onCloseCallback)
|
||||||
{
|
{
|
||||||
_onStateChangeCallback = onStateChangeCallback;
|
_onCloseCallback = onCloseCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketTransport::poll()
|
void WebSocketTransport::poll()
|
||||||
@ -334,6 +341,17 @@ namespace ix {
|
|||||||
_txbuf.insert(_txbuf.end(), buffer.begin(), buffer.end());
|
_txbuf.insert(_txbuf.end(), buffer.begin(), buffer.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocketTransport::unmaskReceiveBuffer(const wsheader_type& ws)
|
||||||
|
{
|
||||||
|
if (ws.mask)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j != ws.N; ++j)
|
||||||
|
{
|
||||||
|
_rxbuf[j+ws.header_size] ^= ws.masking_key[j&0x3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol
|
// http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol
|
||||||
//
|
//
|
||||||
@ -358,8 +376,8 @@ namespace ix {
|
|||||||
//
|
//
|
||||||
void WebSocketTransport::dispatch(const OnMessageCallback& onMessageCallback)
|
void WebSocketTransport::dispatch(const OnMessageCallback& onMessageCallback)
|
||||||
{
|
{
|
||||||
// TODO: consider acquiring a lock on _rxbuf...
|
while (true)
|
||||||
while (true) {
|
{
|
||||||
wsheader_type ws;
|
wsheader_type ws;
|
||||||
if (_rxbuf.size() < 2) return; /* Need at least 2 */
|
if (_rxbuf.size() < 2) return; /* Need at least 2 */
|
||||||
const uint8_t * data = (uint8_t *) &_rxbuf[0]; // peek, but don't consume
|
const uint8_t * data = (uint8_t *) &_rxbuf[0]; // peek, but don't consume
|
||||||
@ -434,13 +452,7 @@ namespace ix {
|
|||||||
|| ws.opcode == wsheader_type::BINARY_FRAME
|
|| ws.opcode == wsheader_type::BINARY_FRAME
|
||||||
|| ws.opcode == wsheader_type::CONTINUATION
|
|| ws.opcode == wsheader_type::CONTINUATION
|
||||||
) {
|
) {
|
||||||
if (ws.mask)
|
unmaskReceiveBuffer(ws);
|
||||||
{
|
|
||||||
for (size_t j = 0; j != ws.N; ++j)
|
|
||||||
{
|
|
||||||
_rxbuf[j+ws.header_size] ^= ws.masking_key[j&0x3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_receivedData.insert(_receivedData.end(),
|
_receivedData.insert(_receivedData.end(),
|
||||||
_rxbuf.begin()+ws.header_size,
|
_rxbuf.begin()+ws.header_size,
|
||||||
_rxbuf.begin()+ws.header_size+(size_t)ws.N);// just feed
|
_rxbuf.begin()+ws.header_size+(size_t)ws.N);// just feed
|
||||||
@ -456,14 +468,7 @@ namespace ix {
|
|||||||
}
|
}
|
||||||
else if (ws.opcode == wsheader_type::PING)
|
else if (ws.opcode == wsheader_type::PING)
|
||||||
{
|
{
|
||||||
if (ws.mask)
|
unmaskReceiveBuffer(ws);
|
||||||
{
|
|
||||||
for (size_t j = 0; j != ws.N; ++j)
|
|
||||||
{
|
|
||||||
_rxbuf[j+ws.header_size] ^= ws.masking_key[j&0x3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pingData(_rxbuf.begin()+ws.header_size,
|
std::string pingData(_rxbuf.begin()+ws.header_size,
|
||||||
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
||||||
|
|
||||||
@ -475,21 +480,37 @@ namespace ix {
|
|||||||
}
|
}
|
||||||
else if (ws.opcode == wsheader_type::PONG)
|
else if (ws.opcode == wsheader_type::PONG)
|
||||||
{
|
{
|
||||||
if (ws.mask)
|
unmaskReceiveBuffer(ws);
|
||||||
{
|
|
||||||
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,
|
std::string pongData(_rxbuf.begin()+ws.header_size,
|
||||||
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
||||||
|
|
||||||
onMessageCallback(pongData, PONG);
|
onMessageCallback(pongData, PONG);
|
||||||
}
|
}
|
||||||
else if (ws.opcode == wsheader_type::CLOSE) { close(); }
|
else if (ws.opcode == wsheader_type::CLOSE)
|
||||||
else { close(); }
|
{
|
||||||
|
unmaskReceiveBuffer(ws);
|
||||||
|
|
||||||
|
// Extract the close code first, available as the first 2 bytes
|
||||||
|
uint16_t code = 0;
|
||||||
|
code |= ((uint64_t) _rxbuf[ws.header_size]) << 8;
|
||||||
|
code |= ((uint64_t) _rxbuf[ws.header_size+1]) << 0;
|
||||||
|
|
||||||
|
// Get the reason.
|
||||||
|
std::string reason(_rxbuf.begin()+ws.header_size + 2,
|
||||||
|
_rxbuf.begin()+ws.header_size + 2 + (size_t) ws.N);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_closeDataMutex);
|
||||||
|
_closeCode = code;
|
||||||
|
_closeReason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
_rxbuf.erase(_rxbuf.begin(),
|
_rxbuf.erase(_rxbuf.begin(),
|
||||||
_rxbuf.begin() + ws.header_size + (size_t) ws.N);
|
_rxbuf.begin() + ws.header_size + (size_t) ws.N);
|
||||||
|
@ -63,7 +63,8 @@ namespace ix
|
|||||||
|
|
||||||
using OnMessageCallback = std::function<void(const std::string&,
|
using OnMessageCallback = std::function<void(const std::string&,
|
||||||
MessageKind)>;
|
MessageKind)>;
|
||||||
using OnStateChangeCallback = std::function<void(ReadyStateValues)>;
|
using OnCloseCallback = std::function<void(uint16_t,
|
||||||
|
const std::string&)>;
|
||||||
|
|
||||||
WebSocketTransport();
|
WebSocketTransport();
|
||||||
~WebSocketTransport();
|
~WebSocketTransport();
|
||||||
@ -79,7 +80,7 @@ namespace ix
|
|||||||
void close();
|
void close();
|
||||||
ReadyStateValues getReadyState() const;
|
ReadyStateValues getReadyState() const;
|
||||||
void setReadyState(ReadyStateValues readyStateValue);
|
void setReadyState(ReadyStateValues readyStateValue);
|
||||||
void setOnStateChangeCallback(const OnStateChangeCallback& onStateChangeCallback);
|
void setOnCloseCallback(const OnCloseCallback& onCloseCallback);
|
||||||
void dispatch(const OnMessageCallback& onMessageCallback);
|
void dispatch(const OnMessageCallback& onMessageCallback);
|
||||||
|
|
||||||
static void printUrl(const std::string& url);
|
static void printUrl(const std::string& url);
|
||||||
@ -120,7 +121,10 @@ namespace ix
|
|||||||
|
|
||||||
std::atomic<ReadyStateValues> _readyState;
|
std::atomic<ReadyStateValues> _readyState;
|
||||||
|
|
||||||
OnStateChangeCallback _onStateChangeCallback;
|
OnCloseCallback _onCloseCallback;
|
||||||
|
uint16_t _closeCode;
|
||||||
|
std::string _closeReason;
|
||||||
|
mutable std::mutex _closeDataMutex;
|
||||||
|
|
||||||
void sendOnSocket();
|
void sendOnSocket();
|
||||||
void sendData(wsheader_type::opcode_type type,
|
void sendData(wsheader_type::opcode_type type,
|
||||||
@ -137,5 +141,6 @@ namespace ix
|
|||||||
void appendToSendBuffer(const std::vector<uint8_t>& buffer);
|
void appendToSendBuffer(const std::vector<uint8_t>& buffer);
|
||||||
|
|
||||||
unsigned getRandomUnsigned();
|
unsigned getRandomUnsigned();
|
||||||
|
void unmaskReceiveBuffer(const wsheader_type& ws);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user