SNode.C
Loading...
Searching...
No Matches
SocketConnection.cpp
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
44#include "core/socket/stream/SocketContext.h"
45#include "core/socket/stream/SocketContextFactory.h"
46#include "net/config/ConfigInstance.h"
47
48#ifndef DOXYGEN_SHOULD_SKIP_THIS
49
50#include "log/Logger.h"
51
52#include <ctime>
53#include <iomanip>
54#include <sstream>
55#include <vector>
56struct tm;
57
58#endif // DOXYGEN_SHOULD_SKIP_THIS
59
60namespace core::socket::stream {
61
62 SocketConnection::SocketConnection(int fd, const net::config::ConfigInstance* config)
64 , connectionName("[" + std::to_string(fd) + "]" + (!instanceName.empty() ? " " : "") + instanceName)
65 , onlineSinceTimePoint(std::chrono::system_clock::now())
66 , config(config) {
67 }
68
70 }
71
72 void SocketConnection::setSocketContext(const std::shared_ptr<SocketContextFactory>& socketContextFactory) {
73 SocketContext* socketContext = socketContextFactory->create(this);
74
75 if (socketContext != nullptr) {
76 LOG(DEBUG) << connectionName << ": SocketContext created successful";
77 setSocketContext(socketContext);
78 } else {
79 LOG(ERROR) << connectionName << ": SocketContext failed to create";
80 close();
81 }
82 }
83
85 if (this->socketContext != nullptr) {
87 }
88
89 this->socketContext = socketContext;
90
91 socketContext->attach();
92 }
93
94 void SocketConnection::sendToPeer(const std::string& data) {
95 sendToPeer(data.data(), data.size());
96 }
97
98 void SocketConnection::sentToPeer(const std::vector<uint8_t>& data) {
99 sendToPeer(reinterpret_cast<const char*>(data.data()), data.size());
100 }
101
102 void SocketConnection::sentToPeer(const std::vector<char>& data) {
103 sendToPeer(data.data(), data.size());
104 }
105
106 const std::string& SocketConnection::getInstanceName() const {
107 return instanceName;
108 }
109
110 const std::string& SocketConnection::getConnectionName() const {
111 return connectionName;
112 }
113
115 return socketContext;
116 }
117
118 std::string SocketConnection::getOnlineSince() const {
120 }
121
122 std::string SocketConnection::getOnlineDuration() const {
124 }
125
126 const net::config::ConfigInstance* SocketConnection::getConfig() const {
127 return config;
128 }
129
130 std::string SocketConnection::timePointToString(const std::chrono::time_point<std::chrono::system_clock>& timePoint) {
131 const std::time_t time = std::chrono::system_clock::to_time_t(timePoint);
132 std::tm* tm_ptr = std::gmtime(&time);
133
134 char buffer[100];
135 std::string onlineSince = "Formatting error";
136
137 // Format: "2025-02-02 14:30:00"
138 if (std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_ptr) > 0) {
139 onlineSince = std::string(buffer) + " UTC";
140 }
141
142 return onlineSince;
143 }
144
145 std::string SocketConnection::durationToString(const std::chrono::time_point<std::chrono::system_clock>& bevore,
146 const std::chrono::time_point<std::chrono::system_clock>& later) {
147 using seconds_duration_type = std::chrono::duration<std::chrono::seconds::rep>::rep;
148
149 const seconds_duration_type totalSeconds = std::chrono::duration_cast<std::chrono::seconds>(later - bevore).count();
150
151 // Compute days, hours, minutes, and seconds
152 const seconds_duration_type days = totalSeconds / 86400; // 86400 seconds in a day
153 seconds_duration_type remainder = totalSeconds % 86400;
154 const seconds_duration_type hours = remainder / 3600;
155 remainder = remainder % 3600;
156 const seconds_duration_type minutes = remainder / 60;
157 const seconds_duration_type seconds = remainder % 60;
158
159 // Format the components into a string using stringstream
160 std::ostringstream oss;
161 if (days > 0) {
162 oss << days << " day" << (days == 1 ? "" : "s") << ", ";
163 }
164 oss << std::setw(2) << std::setfill('0') << hours << ":" << std::setw(2) << std::setfill('0') << minutes << ":" << std::setw(2)
165 << std::setfill('0') << seconds;
166
167 return oss.str();
168 }
169
170} // namespace core::socket::stream
virtual void sendToPeer(const char *chunk, std::size_t chunkLen)=0
SocketConnection(int fd, const net::config::ConfigInstance *config)
core::socket::stream::SocketContext * socketContext
static std::string timePointToString(const std::chrono::time_point< std::chrono::system_clock > &timePoint)
void sentToPeer(const std::vector< char > &data)
void sentToPeer(const std::vector< uint8_t > &data)
void setSocketContext(const std::shared_ptr< SocketContextFactory > &socketContextFactory)
static std::string durationToString(const std::chrono::time_point< std::chrono::system_clock > &bevore, const std::chrono::time_point< std::chrono::system_clock > &later=std::chrono::system_clock::now())
const std::string & getConnectionName() const
void setSocketContext(SocketContext *socketContext)
void sendToPeer(const std::string &data)
std::chrono::time_point< std::chrono::system_clock > onlineSinceTimePoint
const net::config::ConfigInstance * getConfig() const
const std::string & getInstanceName() const
virtual core::socket::stream::SocketContext * create(core::socket::stream::SocketConnection *socketConnection)=0
const std::string & getInstanceName() const