SNode.C
Loading...
Searching...
No Matches
SocketClient.h
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#ifndef CORE_SOCKET_STREAM_SOCKETCLIENT_H
21#define CORE_SOCKET_STREAM_SOCKETCLIENT_H
22
23#include "core/SNodeC.h"
24#include "core/socket/Socket.h" // IWYU pragma: export
25#include "core/socket/State.h" // IWYU pragma: export
26#include "core/socket/stream/SocketContextFactory.h"
27#include "core/timer/Timer.h"
28
29#ifndef DOXYGEN_SHOULD_SKIP_THIS
30
31#include "log/Logger.h"
32#include "utils/Random.h"
33
34#include <algorithm>
35#include <functional> // IWYU pragma: export
36
37#endif /* DOXYGEN_SHOULD_SKIP_THIS */
38
39namespace core::socket::stream {
40
41 /** Sequence diagram showing how a connect to a peer is performed.
42 @startuml
43 !include core/socket/stream/pu/SocketClient.pu
44 @enduml
45 */
46 template <typename SocketConnectorT, typename SocketContextFactoryT, typename... Args>
48 class SocketClient : public core::socket::Socket<typename SocketConnectorT::Config> {
49 private:
52
54
55 public:
58
70
77
78 // VLOG() is used hire as this are log messages for the application
81 name,
82 [name](SocketConnection* socketConnection) { // onConnect
83 VLOG(2) << name << ": OnConnect";
84
85 VLOG(2) << " Local: " << socketConnection->getLocalAddress().toString();
86 VLOG(2) << " Peer: " << socketConnection->getRemoteAddress().toString();
87 },
88 [name](SocketConnection* socketConnection) { // onConnected
89 VLOG(2) << name << ": OnConnected ";
90
91 VLOG(2) << " Local: " << socketConnection->getLocalAddress().toString();
92 VLOG(2) << " Peer: " << socketConnection->getRemoteAddress().toString();
93 },
94 [name](SocketConnection* socketConnection) { // onDisconnect
95 VLOG(2) << name << ": OnDisconnect ";
96
97 VLOG(2) << " Local: " << socketConnection->getLocalAddress().toString();
98 VLOG(2) << " Peer: " << socketConnection->getRemoteAddress().toString();
99 },
100 std::forward<Args>(args)...) {
101 }
102
103 explicit SocketClient(Args&&... args)
104 : SocketClient("", std::forward<Args>(args)...) {
105 }
106
107 private:
109 unsigned int tries,
110 double retryTimeoutScale) const {
111 if (core::SNodeC::state() == core::State::RUNNING || core::SNodeC::state() == core::State::INITIALIZED) {
112 new SocketConnector(
114 onConnect,
118
121
122 LOG(INFO) << client.getConfig().getInstanceName() << ": OnStatus";
123 LOG(INFO) << " reconnecting in " << relativeReconnectTimeout << " seconds";
124
126 [client, onStatus]() {
129
131 },
133 }
134 },
136 bool retry = (state & core::socket::State::NO_RETRY) == 0 &&
139
141
142 switch (state) {
143 case core::socket::State::OK:
144 [[fallthrough]];
145 case core::socket::State::DISABLED:
146 retry = false;
147 break;
148 case core::socket::State::ERROR:
150 break;
151 case core::socket::State::FATAL:
153 break;
154 }
155
156 if (retry) {
164
165 LOG(INFO) << client.getConfig().getInstanceName() << ": OnStatus";
166 LOG(INFO) << " retrying in " << relativeRetryTimeout << " seconds";
167
169 [client, onStatus, tries, retryTimeoutScale]() mutable {
172
174 },
176 }
177 },
178 Super::config);
179 }
180 }
181
182 public:
183 void connect(const std::function<void(const SocketAddress&, core::socket::State)>& onStatus) const {
184 realConnect(onStatus, 0, 1);
185 }
186
193
201
204
205 this->onConnect = onConnect;
206
207 return oldOnConnect;
208 }
209
217
225
229
230 private:
232
236 };
237
238} // namespace core::socket::stream
239
240#endif // CORE_SOCKET_STREAM_SOCKETCLIENT_H
void onReceivedFromPeer(std::size_t available) final
void setTimeout(const utils::Timeval &timeout) final
std::size_t readFromPeer(char *chunk, std::size_t chunkLen) final
const SocketAddress & getRemoteAddress() const final
SocketConnectionT(const std::string &instanceName, PhysicalSocket &&physicalSocket, const std::function< void()> &onDisconnect, const std::string &configuredServer, const SocketAddress &localAddress, const SocketAddress &remoteAddress, const utils::Timeval &readTimeout, const utils::Timeval &writeTimeout, std::size_t readBlockSize, std::size_t writeBlockSize, const utils::Timeval &terminateTimeout)
void doWriteShutdown(const std::function< void()> &onShutdown) override
bool streamToPeer(core::pipe::Source *source) final
void shutdownWrite(bool forceClose) final
void sendToPeer(const char *chunk, std::size_t chunkLen) final
const SocketAddress & getLocalAddress() const final
const std::string & getConfiguredServer() const
virtual void sendToPeer(const char *chunk, std::size_t chunkLen)=0
core::socket::stream::SocketContext * newSocketContext
core::socket::stream::SocketContext * socketContext
void connectSocketContext(const std::shared_ptr< SocketContextFactory > &socketContextFactory)
void switchSocketContext(SocketContext *newSocketContext)
virtual const core::socket::SocketAddress & getLocalAddress() const =0
virtual void setTimeout(const utils::Timeval &timeout)=0
void sentToPeer(const std::vector< uint8_t > &data)
const std::string & getConnectionName() const
void setSocketContext(SocketContext *socketContext)
virtual const core::socket::SocketAddress & getRemoteAddress() const =0
void sendToPeer(const std::string &data)
virtual void shutdownWrite(bool forceClose)=0
virtual std::size_t readFromPeer(char *chunk, std::size_t chunkLen)=0
SocketConnection(const std::string &instanceName, int fd, const std::string &configuredServer)
virtual bool streamToPeer(core::pipe::Source *source)=0
const std::string & getInstanceName() const
SocketConnector(const SocketConnector &socketConnector)
std::function< void(const SocketAddress &, core::socket::State)> onStatus
std::function< void(SocketConnection *)> onConnected
std::shared_ptr< core::socket::stream::SocketContextFactory > socketContextFactory
std::function< void(SocketConnection *)> onDisconnect
std::function< void(SocketConnection *)> onConnect
SocketConnector(const std::shared_ptr< core::socket::stream::SocketContextFactory > &socketContextFactory, const std::function< void(SocketConnection *)> &onConnect, const std::function< void(SocketConnection *)> &onConnected, const std::function< void(SocketConnection *)> &onDisconnect, const std::function< void(const SocketAddress &, core::socket::State)> &onStatus, const std::shared_ptr< Config > &config)
SocketConnection(const std::string &instanceName, PhysicalSocket &&physicalSocket, const std::function< void(SocketConnection *)> &onDisconnect, const std::string &configuredServer, const SocketAddress &localAddress, const SocketAddress &remoteAddress, const utils::Timeval &readTimeout, const utils::Timeval &writeTimeout, std::size_t readBlockSize, std::size_t writeBlockSize, const utils::Timeval &terminateTimeout)
SocketConnector(const std::shared_ptr< core::socket::stream::SocketContextFactory > &socketContextFactory, const std::function< void(SocketConnection *)> &onConnect, const std::function< void(SocketConnection *)> &onConnected, const std::function< void(SocketConnection *)> &onDisconnect, const std::function< void(const SocketAddress &, core::socket::State)> &onStatus, const std::shared_ptr< Config > &config)
SocketConnector(const SocketConnector &socketConnector)
void connect(const std::string &ipOrHostname, uint16_t port, const std::string &bindHost, const std::function< void(const SocketAddress &, core::socket::State)> &onStatus) const
void connect(const std::string &ipOrHostname, uint16_t port, const std::string &bindHost, uint16_t bindPort, const std::function< void(const SocketAddress &, core::socket::State)> &onStatus) const
void connect(const std::string &ipOrHostname, uint16_t port, uint16_t bindPort, const std::function< void(const SocketAddress &, core::socket::State)> &onStatus) const
void connect(const std::string &ipOrHostname, uint16_t port, const std::function< void(const SocketAddress &, core::socket::State)> &onStatus) const
int main(int argc, char *argv[])
Definition Config.h:37