SNode.C
Loading...
Searching...
No Matches
SubProtocol.hpp
Go to the documentation of this file.
1/*
2 * SNode.C - a slim toolkit for network communication
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2020, 2021, 2022, 2023, 2024, 2025
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "core/socket/stream/SocketConnection.h"
21#include "web/websocket/SubProtocol.h"
22#include "web/websocket/SubProtocolContext.h" // IWYU pragma: export
23
24#ifndef DOXYGEN_SHOULD_SKIP_THIS
25
26#include "log/Logger.h"
27
28#include <cstddef>
29#include <cstdint>
30#include <string>
31
32#endif /* DOXYGEN_SHOULD_SKIP_THIS */
33
34namespace web::websocket {
35
36 template <typename SocketContextUpgrade>
37 SubProtocol<SocketContextUpgrade>::SubProtocol(SubProtocolContext* subProtocolContext,
38 const std::string& name,
39 int pingInterval,
40 int maxFlyingPings)
41 : name(name)
42 , subProtocolContext(subProtocolContext) {
43 if (pingInterval > 0) {
44 pingTimer = core::timer::Timer::intervalTimer(
45 [this, maxFlyingPings](const std::function<void()>& stop) {
46 if (flyingPings < maxFlyingPings) {
47 sendPing();
48 flyingPings++;
49 } else {
50 LOG(WARNING) << getSocketConnection()->getConnectionName() << " WebSocket: MaxFlyingPings exceeded - closing";
51
52 sendClose();
53 stop();
54 }
55 },
56 pingInterval);
57 }
59 getSocketConnection()->setTimeout(0);
60 }
61
62 template <typename SocketContextUpgrade>
63 SubProtocol<SocketContextUpgrade>::~SubProtocol() {
64 pingTimer.cancel();
65 }
67 template <typename SocketContextUpgrade>
68 void SubProtocol<SocketContextUpgrade>::sendMessage(const char* message, std::size_t messageLength) const {
69 subProtocolContext->sendMessage(2, message, messageLength);
70 }
72 template <typename SocketContextUpgrade>
73 void SubProtocol<SocketContextUpgrade>::sendMessage(const std::string& message) const {
74 subProtocolContext->sendMessage(1, message.data(), message.length());
75 }
76
77 template <typename SocketContextUpgrade>
78 void SubProtocol<SocketContextUpgrade>::sendMessageStart(const char* message, std::size_t messageLength) const {
79 subProtocolContext->sendMessageStart(2, message, messageLength);
80 }
81
82 template <typename SocketContextUpgrade>
83 void SubProtocol<SocketContextUpgrade>::sendMessageStart(const std::string& message) const {
84 subProtocolContext->sendMessageStart(1, message.data(), message.length());
85 }
87 template <typename SocketContextUpgrade>
88 void SubProtocol<SocketContextUpgrade>::sendMessageFrame(const char* message, std::size_t messageLength) const {
89 subProtocolContext->sendMessageFrame(message, messageLength);
90 }
91
92 template <typename SocketContextUpgrade>
93 void SubProtocol<SocketContextUpgrade>::sendMessageFrame(const std::string& message) const {
94 sendMessageFrame(message.data(), message.length());
95 }
96
97 template <typename SocketContextUpgrade>
98 void SubProtocol<SocketContextUpgrade>::sendMessageEnd(const char* message, std::size_t messageLength) const {
99 subProtocolContext->sendMessageEnd(message, messageLength);
100 }
101
102 template <typename SocketContextUpgrade>
103 void SubProtocol<SocketContextUpgrade>::sendMessageEnd(const std::string& message) const {
104 sendMessageEnd(message.data(), message.length());
105 }
106
107 template <typename SocketContextUpgrade>
108 void SubProtocol<SocketContextUpgrade>::sendPing(const char* reason, std::size_t reasonLength) const {
109 LOG(DEBUG) << getSocketConnection()->getConnectionName() << " WebSocket: Ping sent";
110
111 subProtocolContext->sendPing(reason, reasonLength);
112 }
113
114 template <typename SocketContextUpgrade>
115 void SubProtocol<SocketContextUpgrade>::sendClose(uint16_t statusCode, const char* reason, std::size_t reasonLength) {
116 subProtocolContext->sendClose(statusCode, reason, reasonLength);
117 }
118
119 template <typename SocketContextUpgrade>
120 void SubProtocol<SocketContextUpgrade>::onPongReceived() {
121 LOG(DEBUG) << subProtocolContext->getSocketConnection()->getConnectionName() << " WebSocket: Pong received";
122
123 flyingPings = 0;
124 }
125
126 template <typename SocketContextUpgrade>
127 const std::string& SubProtocol<SocketContextUpgrade>::getName() {
128 return name;
129 }
130
131 template <typename SocketContextUpgrade>
132 core::socket::stream::SocketConnection* SubProtocol<SocketContextUpgrade>::getSocketConnection() const {
133 return subProtocolContext->getSocketConnection();
134 }
135
136} // namespace web::websocket