IXWebSocket/ixwebsocket/IXWebSocketTransport.h

153 lines
4.8 KiB
C
Raw Normal View History

2018-09-27 23:56:48 +02:00
/*
* IXWebSocketTransport.h
* Author: Benjamin Sergeant
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/
#pragma once
//
// Adapted from https://github.com/dhbaird/easywsclient
//
#include <string>
#include <vector>
#include <functional>
#include <memory>
#include <mutex>
2018-10-01 23:46:11 +02:00
#include <atomic>
2018-09-27 23:56:48 +02:00
#include "IXWebSocketSendInfo.h"
#include "IXWebSocketPerMessageDeflate.h"
#include "IXWebSocketPerMessageDeflateOptions.h"
#include "IXWebSocketHttpHeaders.h"
#include "IXCancellationRequest.h"
#include "IXWebSocketHandshake.h"
2018-09-27 23:56:48 +02:00
namespace ix
{
class Socket;
class WebSocketTransport
{
public:
enum ReadyStateValues
{
CLOSING,
CLOSED,
CONNECTING,
OPEN
};
2018-10-25 21:01:47 +02:00
enum MessageKind
{
MSG,
PING,
PONG
};
using OnMessageCallback = std::function<void(const std::string&,
size_t,
2018-11-15 00:52:28 +01:00
bool,
2018-10-25 21:01:47 +02:00
MessageKind)>;
using OnCloseCallback = std::function<void(uint16_t,
const std::string&,
size_t)>;
2018-09-27 23:56:48 +02:00
WebSocketTransport();
~WebSocketTransport();
2019-01-24 21:42:49 +01:00
void configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
int hearBeatPeriod);
2018-09-27 23:56:48 +02:00
2019-01-04 03:33:08 +01:00
WebSocketInitResult connectToUrl(const std::string& url, // Client
int timeoutSecs);
WebSocketInitResult connectToSocket(int fd, // Server
int timeoutSecs);
2018-12-30 06:53:33 +01:00
2018-09-27 23:56:48 +02:00
void poll();
WebSocketSendInfo sendBinary(const std::string& message);
WebSocketSendInfo sendPing(const std::string& message);
2018-09-27 23:56:48 +02:00
void close();
ReadyStateValues getReadyState() const;
void setReadyState(ReadyStateValues readyStateValue);
void setOnCloseCallback(const OnCloseCallback& onCloseCallback);
2018-09-27 23:56:48 +02:00
void dispatch(const OnMessageCallback& onMessageCallback);
private:
std::string _url;
std::string _origin;
struct wsheader_type {
unsigned header_size;
bool fin;
2018-11-07 20:45:17 +01:00
bool rsv1;
2018-09-27 23:56:48 +02:00
bool mask;
enum opcode_type {
CONTINUATION = 0x0,
TEXT_FRAME = 0x1,
BINARY_FRAME = 0x2,
CLOSE = 8,
PING = 9,
PONG = 0xa,
} opcode;
int N0;
uint64_t N;
uint8_t masking_key[4];
};
std::vector<uint8_t> _rxbuf;
std::vector<uint8_t> _txbuf;
mutable std::mutex _txbufMutex;
std::vector<uint8_t> _receivedData;
std::shared_ptr<Socket> _socket;
std::atomic<ReadyStateValues> _readyState;
OnCloseCallback _onCloseCallback;
uint16_t _closeCode;
std::string _closeReason;
size_t _closeWireSize;
mutable std::mutex _closeDataMutex;
2018-09-27 23:56:48 +02:00
WebSocketPerMessageDeflate _perMessageDeflate;
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
std::atomic<bool> _enablePerMessageDeflate;
2018-12-15 01:28:11 +01:00
// Used to cancel dns lookup + socket connect + http upgrade
std::atomic<bool> _requestInitCancellation;
2019-01-24 21:42:49 +01:00
// Optional Heartbeat
int _heartBeatPeriod;
static const int kDefaultHeartBeatPeriod;
const static std::string kHeartBeatPingMessage;
2019-01-26 01:11:39 +01:00
mutable std::mutex _lastSendTimePointMutex;
std::chrono::time_point<std::chrono::steady_clock> _lastSendTimePoint;
// No data was send through the socket for longer that the hearbeat period
bool heartBeatPeriodExceeded();
2018-12-15 01:28:11 +01:00
2018-09-27 23:56:48 +02:00
void sendOnSocket();
WebSocketSendInfo sendData(wsheader_type::opcode_type type,
const std::string& message,
bool compress);
void emitMessage(MessageKind messageKind,
const std::string& message,
const wsheader_type& ws,
const OnMessageCallback& onMessageCallback);
2018-09-27 23:56:48 +02:00
bool isSendBufferEmpty() const;
void appendToSendBuffer(const std::vector<uint8_t>& header,
std::string::const_iterator begin,
std::string::const_iterator end,
uint64_t message_size,
uint8_t masking_key[4]);
void appendToSendBuffer(const std::vector<uint8_t>& buffer);
unsigned getRandomUnsigned();
void unmaskReceiveBuffer(const wsheader_type& ws);
2018-09-27 23:56:48 +02:00
};
}