2018-09-27 23:56:48 +02:00
|
|
|
/*
|
|
|
|
* IXWebSocket.h
|
|
|
|
* Author: Benjamin Sergeant
|
|
|
|
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* WebSocket RFC
|
|
|
|
* https://tools.ietf.org/html/rfc6455
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <thread>
|
|
|
|
#include <mutex>
|
|
|
|
#include <atomic>
|
|
|
|
|
|
|
|
#include "IXWebSocketTransport.h"
|
2018-11-15 00:52:28 +01:00
|
|
|
#include "IXWebSocketErrorInfo.h"
|
2018-11-10 03:23:49 +01:00
|
|
|
#include "IXWebSocketSendInfo.h"
|
|
|
|
#include "IXWebSocketPerMessageDeflateOptions.h"
|
|
|
|
#include "IXWebSocketHttpHeaders.h"
|
2018-09-27 23:56:48 +02:00
|
|
|
|
2018-11-10 03:23:49 +01:00
|
|
|
namespace ix
|
2018-09-27 23:56:48 +02:00
|
|
|
{
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants
|
|
|
|
enum ReadyState
|
|
|
|
{
|
|
|
|
WebSocket_ReadyState_Connecting = 0,
|
|
|
|
WebSocket_ReadyState_Open = 1,
|
|
|
|
WebSocket_ReadyState_Closing = 2,
|
|
|
|
WebSocket_ReadyState_Closed = 3
|
|
|
|
};
|
|
|
|
|
|
|
|
enum WebSocketMessageType
|
|
|
|
{
|
|
|
|
WebSocket_MessageType_Message = 0,
|
|
|
|
WebSocket_MessageType_Open = 1,
|
|
|
|
WebSocket_MessageType_Close = 2,
|
2018-10-25 21:01:47 +02:00
|
|
|
WebSocket_MessageType_Error = 3,
|
|
|
|
WebSocket_MessageType_Ping = 4,
|
|
|
|
WebSocket_MessageType_Pong = 5
|
2018-09-27 23:56:48 +02:00
|
|
|
};
|
|
|
|
|
2019-01-04 02:44:10 +01:00
|
|
|
struct WebSocketOpenInfo
|
|
|
|
{
|
|
|
|
std::string uri;
|
|
|
|
WebSocketHttpHeaders headers;
|
|
|
|
|
|
|
|
WebSocketOpenInfo(const std::string& u = std::string(),
|
|
|
|
const WebSocketHttpHeaders& h = WebSocketHttpHeaders())
|
|
|
|
: uri(u)
|
|
|
|
, headers(h)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-10 03:23:49 +01:00
|
|
|
struct WebSocketCloseInfo
|
2018-10-26 03:51:19 +02:00
|
|
|
{
|
|
|
|
uint16_t code;
|
|
|
|
std::string reason;
|
|
|
|
|
2019-01-06 05:53:50 +01:00
|
|
|
WebSocketCloseInfo(uint16_t c = 0,
|
2018-11-15 00:52:28 +01:00
|
|
|
const std::string& r = std::string())
|
2018-12-06 17:27:28 +01:00
|
|
|
: code(c)
|
|
|
|
, reason(r)
|
2018-10-26 03:51:19 +02:00
|
|
|
{
|
2018-12-06 17:27:28 +01:00
|
|
|
;
|
2018-10-26 03:51:19 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
using OnMessageCallback = std::function<void(WebSocketMessageType,
|
|
|
|
const std::string&,
|
2018-11-10 03:23:49 +01:00
|
|
|
size_t wireSize,
|
|
|
|
const WebSocketErrorInfo&,
|
2019-01-04 02:44:10 +01:00
|
|
|
const WebSocketOpenInfo&,
|
|
|
|
const WebSocketCloseInfo&)>;
|
|
|
|
|
2018-09-27 23:56:48 +02:00
|
|
|
using OnTrafficTrackerCallback = std::function<void(size_t size, bool incoming)>;
|
|
|
|
|
|
|
|
class WebSocket
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
WebSocket();
|
|
|
|
~WebSocket();
|
|
|
|
|
2018-11-10 03:23:49 +01:00
|
|
|
void setUrl(const std::string& url);
|
|
|
|
void setPerMessageDeflateOptions(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
|
2019-01-04 03:33:08 +01:00
|
|
|
void setHandshakeTimeout(int _handshakeTimeoutSecs);
|
2018-11-10 03:23:49 +01:00
|
|
|
|
2019-01-02 06:25:15 +01:00
|
|
|
// Run asynchronously, by calling start and stop.
|
2018-09-27 23:56:48 +02:00
|
|
|
void start();
|
|
|
|
void stop();
|
2019-01-02 06:25:15 +01:00
|
|
|
|
|
|
|
// Run in blocking mode, by connecting first manually, and then calling run.
|
2019-01-04 03:33:08 +01:00
|
|
|
WebSocketInitResult connect(int timeoutSecs);
|
2019-01-02 06:25:15 +01:00
|
|
|
void run();
|
|
|
|
|
2018-11-10 03:23:49 +01:00
|
|
|
WebSocketSendInfo send(const std::string& text);
|
|
|
|
WebSocketSendInfo ping(const std::string& text);
|
2018-09-27 23:56:48 +02:00
|
|
|
void close();
|
|
|
|
|
|
|
|
void setOnMessageCallback(const OnMessageCallback& callback);
|
|
|
|
static void setTrafficTrackerCallback(const OnTrafficTrackerCallback& callback);
|
|
|
|
static void resetTrafficTrackerCallback();
|
|
|
|
|
|
|
|
ReadyState getReadyState() const;
|
2018-11-10 03:23:49 +01:00
|
|
|
const std::string& getUrl() const;
|
|
|
|
const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
|
2018-09-27 23:56:48 +02:00
|
|
|
|
2019-01-02 06:25:15 +01:00
|
|
|
void enableAutomaticReconnection();
|
|
|
|
void disableAutomaticReconnection();
|
|
|
|
|
2018-09-27 23:56:48 +02:00
|
|
|
private:
|
|
|
|
|
2018-11-10 03:23:49 +01:00
|
|
|
WebSocketSendInfo sendMessage(const std::string& text, bool ping);
|
2018-10-25 21:01:47 +02:00
|
|
|
|
2018-09-27 23:56:48 +02:00
|
|
|
bool isConnected() const;
|
|
|
|
bool isClosing() const;
|
|
|
|
void reconnectPerpetuallyIfDisconnected();
|
|
|
|
std::string readyStateToString(ReadyState readyState);
|
|
|
|
static void invokeTrafficTrackerCallback(size_t size, bool incoming);
|
|
|
|
|
2018-12-31 07:00:49 +01:00
|
|
|
// Server
|
|
|
|
void setSocketFileDescriptor(int fd);
|
2019-01-04 03:33:08 +01:00
|
|
|
WebSocketInitResult connectToSocket(int fd, int timeoutSecs);
|
2018-12-31 07:00:49 +01:00
|
|
|
|
2018-09-27 23:56:48 +02:00
|
|
|
WebSocketTransport _ws;
|
|
|
|
|
|
|
|
std::string _url;
|
2018-11-10 03:23:49 +01:00
|
|
|
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
|
|
|
|
mutable std::mutex _configMutex; // protect all config variables access
|
2018-09-27 23:56:48 +02:00
|
|
|
|
|
|
|
OnMessageCallback _onMessageCallback;
|
|
|
|
static OnTrafficTrackerCallback _onTrafficTrackerCallback;
|
|
|
|
|
|
|
|
std::atomic<bool> _stop;
|
|
|
|
std::atomic<bool> _automaticReconnection;
|
|
|
|
std::thread _thread;
|
|
|
|
std::mutex _writeMutex;
|
2018-12-31 07:00:49 +01:00
|
|
|
|
2019-01-04 03:33:08 +01:00
|
|
|
std::atomic<int> _handshakeTimeoutSecs;
|
|
|
|
static const int kDefaultHandShakeTimeoutSecs;
|
|
|
|
|
2018-12-31 07:00:49 +01:00
|
|
|
friend class WebSocketServer;
|
2018-09-27 23:56:48 +02:00
|
|
|
};
|
|
|
|
}
|