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/*
21 * MIT License
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
42#include "core/socket/stream/SocketConnection.h"
43#include "iot/mqtt/SubProtocol.h"
44#include "log/Logger.h"
45#include "utils/system/signal.h"
46#include "web/websocket/SubProtocolContext.h"
47
48#ifndef DOXYGEN_SHOULD_SKIP_THIS
49
50#include "utils/hexdump.h"
51
52#include <algorithm>
53
54#endif // DOXYGEN_SHOULD_SKIP_THIS
55
56namespace iot::mqtt {
57
58 template <typename WSSubProtocolRole>
59 SubProtocol<WSSubProtocolRole>::SubProtocol(web::websocket::SubProtocolContext* subProtocolContext,
60 const std::string& name,
61 iot::mqtt::Mqtt* mqtt)
62 : WSSubProtocolRole(subProtocolContext, name, 0)
63 , iot::mqtt::MqttContext(mqtt)
64 , onReceivedFromPeerEvent([this]([[maybe_unused]] const utils::Timeval& currentTime) {
66
67 if (size > 0) {
69 } else {
70 buffer.clear();
71 cursor = 0;
72 }
73 }) {
74 }
75
76 template <typename WSSubProtocolRole>
77 std::size_t SubProtocol<WSSubProtocolRole>::recv(char* chunk, std::size_t chunklen) {
78 std::size_t maxReturn = std::min(chunklen, size);
79
80 std::copy(buffer.data() + cursor, buffer.data() + cursor + maxReturn, chunk);
81
82 cursor += maxReturn;
83 size -= maxReturn;
84
85 return maxReturn;
86 }
87
88 template <typename WSSubProtocolRole>
89 void SubProtocol<WSSubProtocolRole>::send(const char* chunk, std::size_t chunklen) {
90 WSSubProtocolRole::sendMessage(chunk, chunklen);
91 }
92
93 template <typename WSSubProtocolRole>
94 void SubProtocol<WSSubProtocolRole>::end([[maybe_unused]] bool fatal) {
95 WSSubProtocolRole::sendClose();
96 }
97
98 template <typename WSSubProtocolRole>
99 void SubProtocol<WSSubProtocolRole>::close() {
100 WSSubProtocolRole::sendClose();
101 }
102
103 template <typename WSSubProtocolRole>
104 void SubProtocol<WSSubProtocolRole>::onConnected() {
105 LOG(INFO) << getSocketConnection()->getConnectionName() << " WSMQTT: connected:";
107 }
108
109 template <typename WSSubProtocolRole>
110 void SubProtocol<WSSubProtocolRole>::onMessageStart(int opCode) {
112 LOG(ERROR) << getSocketConnection()->getConnectionName() << " WSMQTT: Wrong Opcode: " << opCode;
113 this->end(true);
114 } else {
115 LOG(DEBUG) << getSocketConnection()->getConnectionName() << " WSMQTT: Message START: " << opCode;
116 }
117 }
118
119 template <typename WSSubProtocolRole>
120 void SubProtocol<WSSubProtocolRole>::onMessageData(const char* chunk, std::size_t chunkLen) {
121 data.append(std::string(chunk, chunkLen));
122
123 LOG(DEBUG) << getSocketConnection()->getConnectionName() << " WebSocket: Frame Data:\n"
124 << std::string(32, ' ').append(utils::hexDump(std::vector<char>(chunk, chunk + chunkLen), 32));
125 }
126
127 template <typename WSSubProtocolRole>
128 void SubProtocol<WSSubProtocolRole>::onMessageEnd() {
129 LOG(DEBUG) << getSocketConnection()->getConnectionName() << " WSMQTT: Message END";
130
131 buffer.insert(buffer.end(), data.begin(), data.end());
132 size += data.size();
133 data.clear();
134
136
137 if (size > 0) {
139 } else {
140 buffer.clear();
141 cursor = 0;
142 }
143 }
144
145 template <typename WSSubProtocolRole>
146 void SubProtocol<WSSubProtocolRole>::onMessageError(uint16_t errnum) {
147 LOG(ERROR) << getSocketConnection()->getConnectionName() << " WSMQTT: Message error: " << errnum;
148 }
149
150 template <typename WSSubProtocolRole>
151 void SubProtocol<WSSubProtocolRole>::onDisconnected() {
153 LOG(DEBUG) << getSocketConnection()->getConnectionName() << " WSMQTT: disconnected:";
154 }
155
156 template <typename WSSubProtocolRole>
157 bool SubProtocol<WSSubProtocolRole>::onSignal(int sig) {
158 bool ret = iot::mqtt::MqttContext::onSignal(sig);
159 LOG(INFO) << getSocketConnection()->getConnectionName() << " WSMQTT: exit due to '" << strsignal(sig) << "' (SIG"
160 << utils::system::sigabbrev_np(sig) << " = " << sig << ")";
161
162 this->sendClose();
163
164 return ret;
165 }
166
167 template <typename WSSubProtocolRole>
168 core::socket::stream::SocketConnection* SubProtocol<WSSubProtocolRole>::getSocketConnection() const {
169 return WSSubProtocolRole::subProtocolContext->getSocketConnection();
170 }
171
172} // namespace iot::mqtt
virtual std::size_t recv(char *chunk, std::size_t chunklen)=0
std::size_t onReceivedFromPeer()
MqttContext(const MqttContext &)=default
MqttContext & operator=(const MqttContext &)=default
virtual void send(const char *chunk, std::size_t chunklen)=0
virtual core::socket::stream::SocketConnection * getSocketConnection() const =0
virtual void end(bool fatal=false)=0
virtual void close()=0
void onEvent(const utils::Timeval &currentTime) override
OnReceivedFromPeerEvent(const std::function< void(const utils::Timeval &)> &onReceivedFromPeer)
std::function< void(const utils::Timeval &)> onReceivedFromPeer
Definition SubProtocol.h:79
void onMessageError(uint16_t errnum) override
bool onSignal(int sig) override
void send(const char *chunk, std::size_t chunklen) override
void onDisconnected() override
void onConnected() override
void close() override
void end(bool fatal=false) override
core::socket::stream::SocketConnection * getSocketConnection() const override
std::size_t recv(char *chunk, std::size_t chunklen) override
std::vector< char > buffer
OnReceivedFromPeerEvent onReceivedFromPeerEvent
void onMessageData(const char *chunk, std::size_t chunkLen) override
SubProtocol(web::websocket::SubProtocolContext *subProtocolContext, const std::string &name, iot::mqtt::Mqtt *mqtt)
void onMessageEnd() override
void onMessageStart(int opCode) override
~SubProtocol() override=default
std::string sigabbrev_np(int sig)
Definition signal.cpp:59
std::string hexDump(const std::vector< char > &bytes, int prefixLength, bool prefixAtFirstLine)
Definition hexdump.cpp:58