2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
20#include "core/socket/stream/SocketConnection.h"
21#include "web/websocket/SocketContextUpgrade.h"
23#ifndef DOXYGEN_SHOULD_SKIP_THIS
25#include "utils/hexdump.h"
29namespace web::websocket {
31 template <
typename SubProtocol,
typename Request,
typename Response>
34 web::http::SocketContextUpgradeFactory<Request, Response>* socketContextUpgradeFactory,
36 : Super(socketConnection, socketContextUpgradeFactory)
37 , SubProtocolContext(socketConnection, role ==
Role::CLIENT) {
40 template <
typename SubProtocol,
typename Request,
typename Response>
42 Transmitter::sendMessage(opCode, message, messageLength);
45 template <
typename SubProtocol,
typename Request,
typename Response>
48 Transmitter::sendMessageStart(opCode, message, messageLength);
51 template <
typename SubProtocol,
typename Request,
typename Response>
53 Transmitter::sendMessageFrame(message, messageLength);
56 template <
typename SubProtocol,
typename Request,
typename Response>
58 Transmitter::sendMessageEnd(message, messageLength);
61 template <
typename SubProtocol,
typename Request,
typename Response>
63 sendMessage(9, reason, reasonLength);
66 template <
typename SubProtocol,
typename Request,
typename Response>
68 sendMessage(10, reason, reasonLength);
71 template <
typename SubProtocol,
typename Request,
typename Response>
74 std::size_t closePayloadLength = reasonLength + 2;
75 char* closePayload =
new char[closePayloadLength];
77 *
reinterpret_cast<uint16_t*>(closePayload) = htobe16(statusCode);
79 if (reasonLength > 0) {
80 memcpy(closePayload + 2, reason, reasonLength);
83 sendClose(closePayload, closePayloadLength);
85 delete[] closePayload;
88 template <
typename SubProtocol,
typename Request,
typename Response>
91 LOG(DEBUG) <<
this->getSocketConnection()->getConnectionName() <<
" WebSocket: Sending close to peer";
93 sendMessage(8, message, messageLength);
101 template <
typename SubProtocol,
typename Request,
typename Response>
103 return web::http::SocketContextUpgrade<Request, Response>::getSocketConnection();
106 template <
typename SubProtocol,
typename Request,
typename Response>
111 case SubProtocolContext::OpCode::CLOSE:
113 case SubProtocolContext::OpCode::PING:
115 case SubProtocolContext::OpCode::PONG:
123 template <
typename SubProtocol,
typename Request,
typename Response>
126 case SubProtocolContext::OpCode::CLOSE:
128 case SubProtocolContext::OpCode::PING:
130 case SubProtocolContext::OpCode::PONG:
131 pongCloseData += std::string(chunk,
static_cast<std::size_t>(chunkLen));
134 std::size_t chunkOffset = 0;
137 std::size_t sendChunkLen =
138 (chunkLen - chunkOffset <= SIZE_MAX) ?
static_cast<std::size_t>(chunkLen - chunkOffset) : SIZE_MAX;
139 subProtocol->onMessageData(chunk + chunkOffset, sendChunkLen);
140 chunkOffset += sendChunkLen;
141 }
while (chunkLen - chunkOffset > 0);
146 template <
typename SubProtocol,
typename Request,
typename Response>
149 case SubProtocolContext::OpCode::CLOSE:
152 LOG(DEBUG) << getSocketConnection()->getConnectionName() <<
" WebSocket: Close confirmed from peer";
154 LOG(DEBUG) << getSocketConnection()->getConnectionName() <<
" WebSocket: Close request received - replying with close";
155 sendClose(pongCloseData.data(), pongCloseData.length());
156 pongCloseData.clear();
160 case SubProtocolContext::OpCode::PING:
161 sendPong(pongCloseData.data(), pongCloseData.length());
162 pongCloseData.clear();
164 case SubProtocolContext::OpCode::PONG:
173 template <
typename SubProtocol,
typename Request,
typename Response>
179 template <
typename SubProtocol,
typename Request,
typename Response>
181 LOG(INFO) << getSocketConnection()->getConnectionName() <<
" WebSocket: connected";
185 template <
typename SubProtocol,
typename Request,
typename Response>
188 LOG(INFO) << getSocketConnection()->getConnectionName() <<
" WebSocket: disconnected";
191 template <
typename SubProtocol,
typename Request,
typename Response>
196 template <
typename SubProtocol,
typename Request,
typename Response>
198 return Receiver::receive();
void sendClose(uint16_t statusCode=1000, const char *reason=nullptr, std::size_t reasonLength=0) override
bool onSignal(int sig) override
void onDisconnected() override
void sendPing(const char *reason=nullptr, std::size_t reasonLength=0) override
~SocketContextUpgrade() override=default
void onMessageData(const char *chunk, uint64_t chunkLen) override
SocketContextUpgrade(const SocketContextUpgrade &)=delete
std::string pongCloseData
SocketContextUpgrade & operator=(const SocketContextUpgrade &)=delete
void sendMessage(uint8_t opCode, const char *message, std::size_t messageLength) override
SubProtocol * subProtocol
void onMessageEnd() override
void sendClose(const char *message, std::size_t messageLength) override
void sendMessageFrame(const char *message, std::size_t messageLength) override
void sendMessageEnd(const char *message, std::size_t messageLength) override
SocketContextUpgrade()=delete
std::size_t onReceivedFromPeer() override
SocketContextUpgrade(core::socket::stream::SocketConnection *socketConnection, web::http::SocketContextUpgradeFactory< Request, Response > *socketContextUpgradeFactory, Role role)
void sendPong(const char *reason=nullptr, std::size_t reasonLength=0) override
void sendMessageStart(uint8_t opCode, const char *message, std::size_t messageLength) override
void onMessageStart(int opCode) override
void onConnected() override
core::socket::stream::SocketConnection * getSocketConnection() override
void onMessageError(uint16_t errnum) override
virtual void sendMessage(uint8_t opCode, const char *message, std::size_t messageLength)=0
virtual void sendPing(const char *reason=nullptr, std::size_t reasonLength=0)=0
virtual void sendMessageFrame(const char *message, std::size_t messageLength)=0
SubProtocolContext & operator=(const SubProtocolContext &)=delete
~SubProtocolContext() override
virtual void sendPong(const char *reason=nullptr, std::size_t reasonLength=0)=0
virtual void sendClose(const char *message, std::size_t messageLength)=0
SubProtocolContext(core::socket::stream::SocketConnection *socketConnection, bool role)
virtual void sendMessageEnd(const char *message, std::size_t messageLength)=0
virtual void sendClose(uint16_t statusCode=1000, const char *reason=nullptr, std::size_t reasonLength=0)=0
virtual void sendMessageStart(uint8_t opCode, const char *message, std::size_t messageLength)=0
virtual core::socket::stream::SocketConnection * getSocketConnection()=0
SubProtocolContext(const SubProtocolContext &)=delete
void sendMessageEnd(const char *message, std::size_t messageLength)
void sendFrameData(const char *frame, uint64_t frameLength) const
Transmitter & operator=(const Transmitter &)=delete
std::random_device randomDevice
void sendFrameData(uint8_t data) const
void sendFrameData(uint16_t data) const
void sendMessage(uint8_t opCode, const char *message, std::size_t messageLength)
void sendFrameData(uint32_t data) const
Transmitter(core::socket::stream::SocketConnection *socketConnection, bool masking)
core::socket::stream::SocketConnection * socketConnection
void send(bool end, uint8_t opCode, const char *message, std::size_t messageLength)
void sendFrame(bool fin, uint8_t opCode, const char *payload, uint64_t payloadLength)
void sendFrameData(uint64_t data) const
std::uniform_int_distribution< uint32_t > distribution
Transmitter(const Transmitter &)=delete
void sendMessageStart(uint8_t opCode, const char *message, std::size_t messageLength)
void sendMessageFrame(const char *message, std::size_t messageLength)
~SocketContextUpgrade() override
web::websocket::SubProtocolFactory< SubProtocol > * subProtocolFactory
std::string loadSubProtocol(const std::string &subProtocolName)
SocketContextUpgrade(core::socket::stream::SocketConnection *socketConnection, web::http::SocketContextUpgradeFactory< web::http::client::Request, web::http::client::Response > *socketContextUpgradeFactory)
static SubProtocolFactorySelector * instance()
#define CLOSE_SOCKET_TIMEOUT