E-MailRelay
gserverpeer.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gserverpeer.cpp
19///
20
21#include "gdef.h"
22#include "gserver.h"
23#include "gmonitor.h"
24#include "glog.h"
25#include "gassert.h"
26#include <sstream>
27#include <utility>
28
29GNet::ServerPeer::ServerPeer( EventState es , ServerPeerInfo && peer_info , const LineBuffer::Config & line_buffer_config ) : // NOLINT
30 EventLogging(es.logging()) ,
31 m_es(es.logging(this)) ,
32 m_address(peer_info.m_address) ,
33 m_socket(std::move(peer_info.m_socket)) ,
34 m_sp(*this,m_es,*this,*m_socket,peer_info.m_server_peer_config.socket_protocol_config) ,
35 m_line_buffer(line_buffer_config) ,
36 m_config(peer_info.m_server_peer_config) ,
37 m_idle_timer(*this,&ServerPeer::onIdleTimeout,m_es) ,
38 m_event_logging_string(eventLoggingString(peerAddress(),peer_info.m_server_peer_config))
39{
40 G_ASSERT( peer_info.m_server != nullptr ) ;
41 G_ASSERT( m_socket.get() ) ;
42 G_DEBUG( "GNet::ServerPeer::ctor: [" << this << "]: port " << m_address.port() ) ;
43
44 if( m_config.idle_timeout )
45 m_idle_timer.startTimer( m_config.idle_timeout ) ;
46
47 m_socket->addReadHandler( *this , m_es ) ;
48 m_socket->addOtherHandler( *this , m_es ) ;
49 Monitor::addServerPeer( *this ) ;
50}
51
53{
54 G_DEBUG( "GNet::ServerPeer::dtor: [" << this << "]: port " << m_address.port() ) ;
56}
57
58std::string GNet::ServerPeer::eventLoggingString( const Address & a , const Config & config )
59{
60 // (semi-colon to simplify fail2ban regexes)
61 if( config.log_address && config.log_port )
62 return a.hostPartString().append(1U,';').append(std::to_string(a.port())).append(": ",2U) ;
63 else if( config.log_address )
64 return a.hostPartString().append("; ",2U) ;
65 else if( config.log_port )
66 return std::to_string(a.port()).append(": ",2U) ;
67 else
68 return {} ;
69}
70
72{
73 m_sp.secureAccept() ;
74}
75
77{
78 return m_sp.secureAcceptCapable() ;
79}
80
81#ifndef G_LIB_SMALL
82void GNet::ServerPeer::expect( std::size_t n )
83{
84 m_line_buffer.expect( n ) ;
85}
86#endif
87
89{
90 G_ASSERT( m_socket != nullptr ) ;
91 return *m_socket ;
92}
93
95{
96 socket().dropReadHandler() ;
97}
98
100{
101 socket().addReadHandler( *this , m_es ) ;
102}
103
104void GNet::ServerPeer::otherEvent( EventHandler::Reason reason )
105{
106 m_sp.otherEvent( reason , m_config.no_throw_on_peer_disconnect ) ;
107}
108
109void GNet::ServerPeer::readEvent()
110{
111 if( m_sp.readEvent( m_config.no_throw_on_peer_disconnect ) )
112 onSendComplete() ;
113}
114
116{
117 G_ASSERT( m_socket != nullptr ) ;
118 return m_socket->getLocalAddress() ;
119}
120
122{
123 return m_address ;
124}
125
127{
128 return m_address.displayString() ;
129}
130
132{
133 return m_sp.peerCertificate() ;
134}
135
136bool GNet::ServerPeer::send( const std::string & data )
137{
138 if( m_config.kick_idle_timer_on_send && m_config.idle_timeout )
139 m_idle_timer.startTimer( m_config.idle_timeout ) ;
140 return m_sp.send( data , 0U ) ;
141}
142
143bool GNet::ServerPeer::send( std::string_view data )
144{
145 if( m_config.kick_idle_timer_on_send && m_config.idle_timeout )
146 m_idle_timer.startTimer( m_config.idle_timeout ) ;
147 return m_sp.send( data ) ;
148}
149
150#ifndef G_LIB_SMALL
151bool GNet::ServerPeer::send( const std::vector<std::string_view> & segments , std::size_t offset )
152{
153 if( m_config.kick_idle_timer_on_send && m_config.idle_timeout )
154 m_idle_timer.startTimer( m_config.idle_timeout ) ;
155 return m_sp.send( segments , offset ) ;
156}
157#endif
158
159void GNet::ServerPeer::writeEvent()
160{
161 if( m_sp.writeEvent() )
162 onSendComplete() ;
163}
164
165void GNet::ServerPeer::doOnDelete( const std::string & reason , bool done )
166{
167 G_DEBUG( "GNet::ServerPeer::doOnDelete: reason=[" << reason << "]" ) ;
168 onDelete( done ? std::string() : reason ) ;
169}
170
171void GNet::ServerPeer::onIdleTimeout()
172{
173 std::ostringstream ss ;
174 ss << "no activity after " << m_config.idle_timeout << "s" ;
175 throw IdleTimeout( ss.str() ) ;
176}
177
178void GNet::ServerPeer::onData( const char * data , std::size_t size )
179{
180 if( m_config.idle_timeout )
181 m_idle_timer.startTimer( m_config.idle_timeout ) ;
182
183 bool fragments = m_line_buffer.transparent() ;
184 m_line_buffer.apply( this , &ServerPeer::onDataImp , data , size , fragments ) ;
185}
186
187bool GNet::ServerPeer::onDataImp( const char * data , std::size_t size , std::size_t eolsize ,
188 std::size_t linesize , char c0 )
189{
190 return onReceive( data , size , eolsize , linesize , c0 ) ;
191}
192
194{
195 return LineBufferState( m_line_buffer ) ;
196}
197
198std::string_view GNet::ServerPeer::eventLoggingString() const
199{
200 if( m_event_logging_string.empty() ) return {} ;
201 return m_event_logging_string ;
202}
203
205{
206 m_config.idle_timeout = s ;
207 m_idle_timer.cancelTimer() ;
208 if( m_config.idle_timeout )
209 m_idle_timer.startTimer( m_config.idle_timeout ) ;
210}
211
212#ifndef G_LIB_SMALL
214{
215 m_sp.shutdown() ;
216}
217#endif
218
219void GNet::ServerPeer::onPeerDisconnect()
220{
221}
222
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:63
unsigned int port() const
Returns port part of the address.
Definition: gaddress.cpp:435
std::string hostPartString() const
Returns a printable string that represents the network address.
Definition: gaddress.cpp:365
An interface for GNet classes that define a logging context string.
Definition: geventlogging.h:47
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
Provides information about the state of a line buffer.
Definition: glinebuffer.h:341
static void addServerPeer(const Connection &server_peer)
Adds a server connection.
Definition: gmonitor.cpp:122
static void removeServerPeer(const Connection &server_peer) noexcept
Removes a server connection.
Definition: gmonitor.cpp:132
A move-only structure used in GNet::Server::newPeer() and containing the new socket.
Definition: gserver.h:142
An abstract base class for the GNet::Server's connection to a remote client.
Definition: gserverpeer.h:59
void expect(std::size_t)
Modifies the line buffer state so that it delivers a chunk of non-line-delimited data.
Definition: gserverpeer.cpp:82
void addReadHandler()
Re-adds the socket() read handler.
Definition: gserverpeer.cpp:99
void dropReadHandler()
Drops the socket() read handler.
Definition: gserverpeer.cpp:94
~ServerPeer() override
Destructor.
Definition: gserverpeer.cpp:52
static std::string eventLoggingString(const Address &, const Config &)
Assembles an event logging string for a new ServerPeer object.
Definition: gserverpeer.cpp:58
bool secureAcceptCapable() const
Returns true if secureAccept() is usable.
Definition: gserverpeer.cpp:76
void secureAccept()
Waits for the peer to start a secure session.
Definition: gserverpeer.cpp:71
Address peerAddress() const override
Returns the peer address.
std::string connectionState() const override
Returns the connection state display string.
void doOnDelete(const std::string &reason, bool done)
Used by the GNet::Server class to call onDelete().
void setIdleTimeout(unsigned int seconds)
Sets the idle timeout.
Address localAddress() const override
Returns the local address.
LineBufferState lineBuffer() const
Returns information about the state of the internal line-buffer.
ServerPeer(EventState, ServerPeerInfo &&, const LineBuffer::Config &)
Constructor.
Definition: gserverpeer.cpp:29
std::string peerCertificate() const override
Returns the peer's TLS certificate.
bool send(const std::string &data)
Sends data down the socket to the peer.
StreamSocket & socket()
Returns a reference to the client-server connection socket.
Definition: gserverpeer.cpp:88
void onData(const char *, std::size_t) override
Override from GNet::SocketProtocolSink.
void finish()
Does a socket shutdown(). See also GNet::Client::finish().
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:356
STL namespace.
A configuration structure for GNet::LineBuffer.
Definition: glinebuffer.h:92
A configuration structure for GNet::ServerPeer.
Definition: gserverpeer.h:64