2018-09-27 14:56:48 -07: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
|
|
|
|
|
2019-05-30 08:46:50 -07:00
|
|
|
#include "IXProgressCallback.h"
|
2019-09-22 18:06:15 -07:00
|
|
|
#include "IXSocketTLSOptions.h"
|
2019-05-30 08:46:50 -07:00
|
|
|
#include "IXWebSocketCloseConstants.h"
|
2018-11-14 15:52:28 -08:00
|
|
|
#include "IXWebSocketErrorInfo.h"
|
2018-11-09 18:23:49 -08:00
|
|
|
#include "IXWebSocketHttpHeaders.h"
|
2019-06-09 11:33:17 -07:00
|
|
|
#include "IXWebSocketMessage.h"
|
2019-05-30 08:46:50 -07:00
|
|
|
#include "IXWebSocketPerMessageDeflateOptions.h"
|
|
|
|
#include "IXWebSocketSendInfo.h"
|
|
|
|
#include "IXWebSocketTransport.h"
|
|
|
|
#include <atomic>
|
|
|
|
#include <mutex>
|
|
|
|
#include <string>
|
|
|
|
#include <thread>
|
2018-09-27 14:56:48 -07:00
|
|
|
|
2018-11-09 18:23:49 -08:00
|
|
|
namespace ix
|
2018-09-27 14:56:48 -07:00
|
|
|
{
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants
|
2019-05-12 00:22:06 +03:00
|
|
|
enum class ReadyState
|
2018-09-27 14:56:48 -07:00
|
|
|
{
|
2019-05-30 08:46:50 -07:00
|
|
|
Connecting = 0,
|
|
|
|
Open = 1,
|
|
|
|
Closing = 2,
|
|
|
|
Closed = 3
|
2018-09-27 14:56:48 -07:00
|
|
|
};
|
|
|
|
|
2019-06-09 11:33:17 -07:00
|
|
|
using OnMessageCallback = std::function<void(const WebSocketMessagePtr&)>;
|
2019-01-03 17:44:10 -08:00
|
|
|
|
2018-09-27 14:56:48 -07:00
|
|
|
using OnTrafficTrackerCallback = std::function<void(size_t size, bool incoming)>;
|
|
|
|
|
2019-02-20 18:59:07 -08:00
|
|
|
class WebSocket
|
2018-09-27 14:56:48 -07:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
WebSocket();
|
|
|
|
~WebSocket();
|
|
|
|
|
2018-11-09 18:23:49 -08:00
|
|
|
void setUrl(const std::string& url);
|
2019-08-26 10:19:09 -07:00
|
|
|
|
|
|
|
// send extra headers in client handshake request
|
|
|
|
void setExtraHeaders(const WebSocketHttpHeaders& headers);
|
2019-05-30 08:46:50 -07:00
|
|
|
void setPerMessageDeflateOptions(
|
|
|
|
const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
|
2019-09-22 18:06:15 -07:00
|
|
|
void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
|
2019-04-18 18:24:16 +02:00
|
|
|
void setHeartBeatPeriod(int heartBeatPeriodSecs);
|
|
|
|
void setPingInterval(int pingIntervalSecs); // alias of setHeartBeatPeriod
|
|
|
|
void setPingTimeout(int pingTimeoutSecs);
|
|
|
|
void enablePong();
|
|
|
|
void disablePong();
|
2019-06-06 13:48:53 -07:00
|
|
|
void disablePerMessageDeflate();
|
2019-10-13 13:37:34 -07:00
|
|
|
void addSubProtocol(const std::string& subProtocol);
|
2019-04-19 16:57:38 -07:00
|
|
|
|
2019-01-01 21:25:15 -08:00
|
|
|
// Run asynchronously, by calling start and stop.
|
2018-09-27 14:56:48 -07:00
|
|
|
void start();
|
2019-05-10 20:47:13 -07:00
|
|
|
|
2019-05-11 19:51:26 +03:00
|
|
|
// stop is synchronous
|
2019-05-16 12:46:53 -07:00
|
|
|
void stop(uint16_t code = WebSocketCloseConstants::kNormalClosureCode,
|
|
|
|
const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
|
2019-01-01 21:25:15 -08:00
|
|
|
|
|
|
|
// Run in blocking mode, by connecting first manually, and then calling run.
|
2019-01-03 18:33:08 -08:00
|
|
|
WebSocketInitResult connect(int timeoutSecs);
|
2019-01-01 21:25:15 -08:00
|
|
|
void run();
|
|
|
|
|
2019-06-09 10:22:27 -07:00
|
|
|
// send is in binary mode by default
|
2019-05-11 22:20:58 +03:00
|
|
|
WebSocketSendInfo send(const std::string& data,
|
2019-06-09 11:55:34 -07:00
|
|
|
bool binary = false,
|
|
|
|
const OnProgressCallback& onProgressCallback = nullptr);
|
2019-06-09 10:22:27 -07:00
|
|
|
WebSocketSendInfo sendBinary(const std::string& text,
|
|
|
|
const OnProgressCallback& onProgressCallback = nullptr);
|
2019-03-22 14:22:58 -07:00
|
|
|
WebSocketSendInfo sendText(const std::string& text,
|
|
|
|
const OnProgressCallback& onProgressCallback = nullptr);
|
2018-11-09 18:23:49 -08:00
|
|
|
WebSocketSendInfo ping(const std::string& text);
|
2019-05-10 20:47:13 -07:00
|
|
|
|
2019-06-09 11:33:17 -07:00
|
|
|
void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode,
|
|
|
|
const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
|
2018-09-27 14:56:48 -07:00
|
|
|
|
|
|
|
void setOnMessageCallback(const OnMessageCallback& callback);
|
|
|
|
static void setTrafficTrackerCallback(const OnTrafficTrackerCallback& callback);
|
|
|
|
static void resetTrafficTrackerCallback();
|
|
|
|
|
|
|
|
ReadyState getReadyState() const;
|
2019-05-12 00:22:06 +03:00
|
|
|
static std::string readyStateToString(ReadyState readyState);
|
|
|
|
|
2018-11-09 18:23:49 -08:00
|
|
|
const std::string& getUrl() const;
|
|
|
|
const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
|
2019-01-24 12:42:49 -08:00
|
|
|
int getHeartBeatPeriod() const;
|
2019-04-18 18:24:16 +02:00
|
|
|
int getPingInterval() const;
|
|
|
|
int getPingTimeout() const;
|
2019-03-13 23:09:45 -07:00
|
|
|
size_t bufferedAmount() const;
|
2018-09-27 14:56:48 -07:00
|
|
|
|
2019-01-01 21:25:15 -08:00
|
|
|
void enableAutomaticReconnection();
|
|
|
|
void disableAutomaticReconnection();
|
2019-05-14 21:26:37 +03:00
|
|
|
bool isAutomaticReconnectionEnabled() const;
|
2019-08-30 12:46:35 -07:00
|
|
|
void setMaxWaitBetweenReconnectionRetries(uint32_t maxWaitBetweenReconnectionRetries);
|
|
|
|
uint32_t getMaxWaitBetweenReconnectionRetries() const;
|
2019-10-13 13:37:34 -07:00
|
|
|
const std::vector<std::string>& getSubProtocols();
|
2019-01-01 21:25:15 -08:00
|
|
|
|
2018-09-27 14:56:48 -07:00
|
|
|
private:
|
2019-02-20 18:59:07 -08:00
|
|
|
WebSocketSendInfo sendMessage(const std::string& text,
|
2019-03-22 14:22:58 -07:00
|
|
|
SendMessageKind sendMessageKind,
|
2019-02-20 18:59:07 -08:00
|
|
|
const OnProgressCallback& callback = nullptr);
|
2018-10-25 12:01:47 -07:00
|
|
|
|
2018-09-27 14:56:48 -07:00
|
|
|
bool isConnected() const;
|
|
|
|
bool isClosing() const;
|
2019-05-11 10:24:28 -07:00
|
|
|
void checkConnection(bool firstConnectionAttempt);
|
2018-09-27 14:56:48 -07:00
|
|
|
static void invokeTrafficTrackerCallback(size_t size, bool incoming);
|
|
|
|
|
2018-12-30 22:00:49 -08:00
|
|
|
// Server
|
2019-09-30 22:06:46 -07:00
|
|
|
WebSocketInitResult connectToSocket(std::shared_ptr<Socket>, int timeoutSecs);
|
2018-12-30 22:00:49 -08:00
|
|
|
|
2018-09-27 14:56:48 -07:00
|
|
|
WebSocketTransport _ws;
|
|
|
|
|
|
|
|
std::string _url;
|
2019-08-26 10:19:09 -07:00
|
|
|
WebSocketHttpHeaders _extraHeaders;
|
2019-08-26 11:37:40 -05:00
|
|
|
|
2018-11-09 18:23:49 -08:00
|
|
|
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
|
2019-09-22 18:06:15 -07:00
|
|
|
|
|
|
|
SocketTLSOptions _socketTLSOptions;
|
|
|
|
|
2018-11-09 18:23:49 -08:00
|
|
|
mutable std::mutex _configMutex; // protect all config variables access
|
2018-09-27 14:56:48 -07:00
|
|
|
|
|
|
|
OnMessageCallback _onMessageCallback;
|
|
|
|
static OnTrafficTrackerCallback _onTrafficTrackerCallback;
|
|
|
|
|
|
|
|
std::atomic<bool> _stop;
|
|
|
|
std::thread _thread;
|
|
|
|
std::mutex _writeMutex;
|
2018-12-30 22:00:49 -08:00
|
|
|
|
2019-08-30 12:46:35 -07:00
|
|
|
// Automatic reconnection
|
|
|
|
std::atomic<bool> _automaticReconnection;
|
|
|
|
static const uint32_t kDefaultMaxWaitBetweenReconnectionRetries;
|
|
|
|
uint32_t _maxWaitBetweenReconnectionRetries;
|
|
|
|
|
2019-01-03 18:33:08 -08:00
|
|
|
std::atomic<int> _handshakeTimeoutSecs;
|
|
|
|
static const int kDefaultHandShakeTimeoutSecs;
|
|
|
|
|
2019-04-18 18:24:16 +02:00
|
|
|
// enable or disable PONG frame response to received PING frame
|
|
|
|
bool _enablePong;
|
|
|
|
static const bool kDefaultEnablePong;
|
|
|
|
|
2019-06-09 10:10:33 -07:00
|
|
|
// Optional ping and pong timeout
|
2019-04-18 18:24:16 +02:00
|
|
|
int _pingIntervalSecs;
|
|
|
|
int _pingTimeoutSecs;
|
|
|
|
static const int kDefaultPingIntervalSecs;
|
|
|
|
static const int kDefaultPingTimeoutSecs;
|
2019-01-24 12:42:49 -08:00
|
|
|
|
2019-10-13 13:37:34 -07:00
|
|
|
// Subprotocols
|
|
|
|
std::vector<std::string> _subProtocols;
|
|
|
|
|
2018-12-30 22:00:49 -08:00
|
|
|
friend class WebSocketServer;
|
2018-09-27 14:56:48 -07:00
|
|
|
};
|
2019-05-30 08:46:50 -07:00
|
|
|
} // namespace ix
|