E-MailRelay
gserverpeer.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 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 "gtest.h"
25#include "glog.h"
26#include "gassert.h"
27#include <sstream>
28#include <utility>
29
30GNet::ServerPeer::ServerPeer( ExceptionSink es , ServerPeerInfo && peer_info , const LineBuffer::Config & line_buffer_config ) :
31 m_es(es) ,
32 m_address(peer_info.m_address) ,
33 m_socket(std::move(peer_info.m_socket)) ,
34 m_sp(*this,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,es)
38{
39 G_ASSERT( peer_info.m_server != nullptr ) ;
40 G_ASSERT( m_socket.get() ) ;
41 //G_ASSERT( es.esrc() != nullptr ) ; // moot
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 , es ) ;
48 m_socket->addOtherHandler( *this , es ) ;
49 Monitor::addServerPeer( *this ) ;
50}
51
53{
54 G_DEBUG( "GNet::ServerPeer::dtor: [" << this << "]: port " << m_address.port() ) ;
56}
57
59{
60 m_sp.secureAccept() ;
61}
62
64{
65 return m_sp.secureAcceptCapable() ;
66}
67
68#ifndef G_LIB_SMALL
69void GNet::ServerPeer::expect( std::size_t n )
70{
71 m_line_buffer.expect( n ) ;
72}
73#endif
74
76{
77 G_ASSERT( m_socket != nullptr ) ;
78 return *m_socket ;
79}
80
82{
83 socket().dropReadHandler() ;
84}
85
87{
88 socket().addReadHandler( *this , m_es ) ;
89}
90
91void GNet::ServerPeer::otherEvent( EventHandler::Reason reason )
92{
93 m_sp.otherEvent( reason , m_config.no_throw_on_peer_disconnect ) ;
94}
95
96void GNet::ServerPeer::readEvent()
97{
98 if( m_sp.readEvent( m_config.no_throw_on_peer_disconnect ) )
99 onSendComplete() ;
100}
101
103{
104 G_ASSERT( m_socket != nullptr ) ;
105 return m_socket->getLocalAddress() ;
106}
107
109{
110 return m_address ;
111}
112
114{
115 return m_address.displayString() ;
116}
117
119{
120 return m_sp.peerCertificate() ;
121}
122
123bool GNet::ServerPeer::send( const std::string & data )
124{
125 if( m_config.kick_idle_timer_on_send && m_config.idle_timeout )
126 m_idle_timer.startTimer( m_config.idle_timeout ) ;
127 return m_sp.send( data , 0U ) ;
128}
129
131{
132 if( m_config.kick_idle_timer_on_send && m_config.idle_timeout )
133 m_idle_timer.startTimer( m_config.idle_timeout ) ;
134 return m_sp.send( data ) ;
135}
136
137#ifndef G_LIB_SMALL
138bool GNet::ServerPeer::send( const std::vector<G::string_view> & segments , std::size_t offset )
139{
140 if( m_config.kick_idle_timer_on_send && m_config.idle_timeout )
141 m_idle_timer.startTimer( m_config.idle_timeout ) ;
142 return m_sp.send( segments , offset ) ;
143}
144#endif
145
146void GNet::ServerPeer::writeEvent()
147{
148 if( m_sp.writeEvent() )
149 onSendComplete() ;
150}
151
152void GNet::ServerPeer::doOnDelete( const std::string & reason , bool done )
153{
154 G_DEBUG( "GNet::ServerPeer::doOnDelete: reason=[" << reason << "]" ) ;
155 onDelete( done ? std::string() : reason ) ;
156}
157
158void GNet::ServerPeer::onIdleTimeout()
159{
160 std::ostringstream ss ;
161 ss << "no activity after " << m_config.idle_timeout << "s" ;
162 throw IdleTimeout( ss.str() ) ;
163}
164
165void GNet::ServerPeer::onData( const char * data , std::size_t size )
166{
167 if( m_config.idle_timeout )
168 m_idle_timer.startTimer( m_config.idle_timeout ) ;
169
170 bool fragments = m_line_buffer.transparent() ;
171 m_line_buffer.apply( this , &ServerPeer::onDataImp , data , size , fragments ) ;
172}
173
174bool GNet::ServerPeer::onDataImp( const char * data , std::size_t size , std::size_t eolsize ,
175 std::size_t linesize , char c0 )
176{
177 return onReceive( data , size , eolsize , linesize , c0 ) ;
178}
179
181{
182 return LineBufferState( m_line_buffer ) ;
183}
184
185std::string GNet::ServerPeer::exceptionSourceId() const
186{
187 if( m_exception_source_id.empty() )
188 {
189 m_exception_source_id = peerAddress().hostPartString() ; // GNet::Connection
190 if( G::Test::enabled("log-full-address") )
191 m_exception_source_id = peerAddress().displayString() ;
192 }
193 return m_exception_source_id ;
194}
195
197{
198 m_config.idle_timeout = s ;
199 m_idle_timer.cancelTimer() ;
200 if( m_config.idle_timeout )
201 m_idle_timer.startTimer( m_config.idle_timeout ) ;
202}
203
204#ifndef G_LIB_SMALL
206{
207 m_sp.shutdown() ;
208}
209#endif
210
211void GNet::ServerPeer::onPeerDisconnect()
212{
213}
214
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:62
unsigned int port() const
Returns port part of the address.
Definition: gaddress.cpp:437
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
Provides information about the state of a line buffer.
Definition: glinebuffer.h:340
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:140
An abstract base class for the GNet::Server's connection to a remote client.
Definition: gserverpeer.h:58
void expect(std::size_t)
Modifies the line buffer state so that it delivers a chunk of non-line-delimited data.
Definition: gserverpeer.cpp:69
void addReadHandler()
Re-adds the socket() read handler.
Definition: gserverpeer.cpp:86
void dropReadHandler()
Drops the socket() read handler.
Definition: gserverpeer.cpp:81
~ServerPeer() override
Destructor.
Definition: gserverpeer.cpp:52
bool secureAcceptCapable() const
Returns true if secureAccept() is usable.
Definition: gserverpeer.cpp:63
void secureAccept()
Waits for the peer to start a secure session.
Definition: gserverpeer.cpp:58
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 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.
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:75
void onData(const char *, std::size_t) override
Override from GNet::SocketProtocolSink.
ServerPeer(ExceptionSink, ServerPeerInfo &&, const LineBuffer::Config &)
Constructor.
Definition: gserverpeer.cpp:30
void finish()
Does a socket shutdown(). See also GNet::Client::finish().
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:341
static bool enabled() noexcept
Returns true if test features are enabled.
Definition: gtest.cpp:79
A class like c++17's std::string_view.
Definition: gstringview.h:51
STL namespace.
A configuration structure for GNet::LineBuffer.
Definition: glinebuffer.h:91