E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gserver.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 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 // gserver.cpp
19 //
20
21 #include "gdef.h"
22 #include "glimits.h"
23 #include "gserver.h"
24 #include "groot.h"
25 #include "gmonitor.h"
26 #include "gdebug.h"
27 #include "gtest.h"
28 #include "gassert.h"
29 #include <algorithm> // std::find()
30
31 GNet::ServerPeer::ServerPeer( Server::PeerInfo peer_info ) :
32 m_address(peer_info.m_address) ,
33 m_socket(peer_info.m_socket) ,
34 m_sp(*this,*this,*this,*m_socket.get(),0U) ,
35 m_handle(peer_info.m_handle) ,
36 m_delete_timer(*this,&ServerPeer::onTimeout,*this)
37 {
38 G_ASSERT( m_socket.get() != nullptr ) ;
39 G_DEBUG( "GNet::ServerPeer::ctor: [" << this << "]: " << logId() ) ;
40
41 m_socket->addReadHandler( *this , *this ) ;
42 m_socket->addOtherHandler( *this , *this ) ;
43 if( Monitor::instance() ) Monitor::instance()->addServerPeer(*this) ;
44 }
45
46 GNet::ServerPeer::~ServerPeer()
47 {
48 G_DEBUG( "GNet::ServerPeer::dtor: [" << this << "]: fd " << logId() ) ;
49 if( Monitor::instance() ) Monitor::instance()->removeServerPeer(*this) ;
50 m_handle->reset() ;
51 m_socket->dropReadHandler() ;
52 m_socket->dropOtherHandler() ;
53 }
54
55 std::string GNet::ServerPeer::logId() const
56 {
57 return m_address.displayString() + "@" + m_socket->asString() ;
58 }
59
60 void GNet::ServerPeer::secureAccept()
61 {
62 m_sp.secureAccept() ;
63 }
64
65 GNet::StreamSocket & GNet::ServerPeer::socket()
66 {
67 G_ASSERT( m_socket.get() != nullptr ) ;
68 return *m_socket.get() ;
69 }
70
71 void GNet::ServerPeer::otherEvent( EventHandler::Reason reason )
72 {
73 m_sp.otherEvent( reason ) ;
74 }
75
76 void GNet::ServerPeer::readEvent()
77 {
78 m_sp.readEvent() ;
79 }
80
81 void GNet::ServerPeer::doDelete( const std::string & reason )
82 {
83 onDelete( reason ) ;
84 m_delete_timer.startTimer( 0U ) ;
85 }
86
87 std::pair<bool,GNet::Address> GNet::ServerPeer::localAddress() const
88 {
89 G_ASSERT( m_socket.get() != nullptr ) ;
90 return m_socket->getLocalAddress() ;
91 }
92
93 std::pair<bool,GNet::Address> GNet::ServerPeer::peerAddress() const
94 {
95 return std::pair<bool,Address>( true , m_address ) ;
96 }
97
98 std::string GNet::ServerPeer::connectionState() const
99 {
100 return m_address.displayString() ;
101 }
102
103 std::string GNet::ServerPeer::peerCertificate() const
104 {
105 return m_sp.peerCertificate() ;
106 }
107
108 void GNet::ServerPeer::onTimeout()
109 {
110 doDeleteThis(1) ;
111 }
112
113 void GNet::ServerPeer::doDeleteThis( int )
114 {
115 delete this ;
116 }
117
118 bool GNet::ServerPeer::send( const std::string & data , std::string::size_type offset )
119 {
120 return m_sp.send( data , offset ) ;
121 }
122
123 bool GNet::ServerPeer::send( const std::vector<std::pair<const char*,size_t> > & segments )
124 {
125 return m_sp.send( segments ) ;
126 }
127
128 void GNet::ServerPeer::writeEvent()
129 {
130 if( m_sp.writeEvent() )
131 onSendComplete() ;
132 }
133
134 void GNet::ServerPeer::onException( std::exception & e )
135 {
136 doDelete( e.what() ) ;
137 }
138
139 // ===
140
141 GNet::Server::Server( ExceptionHandler & eh , const Address & listening_address ) :
142 m_eh(eh)
143 {
144 init( listening_address ) ;
145 }
146
147 GNet::Server::Server( ExceptionHandler & eh ) :
148 m_eh(eh) ,
149 m_cleaned_up(false)
150 {
151 }
152
153 void GNet::Server::init( const Address & listening_address )
154 {
155 m_cleaned_up = false ;
156 m_socket.reset( new StreamSocket(listening_address.domain(),StreamSocket::Listener()) ) ;
157 G_DEBUG( "GNet::Server::init: listening on socket " << m_socket->asString() << " with address " << listening_address.displayString() ) ;
158 {
159 G::Root claim_root ;
160 m_socket->bind( listening_address ) ;
161 }
162 m_socket->listen( G::limits::net_listen_queue ) ;
163 m_socket->addReadHandler( *this , m_eh ) ;
164 }
165
166 bool GNet::Server::canBind( const Address & address , bool do_throw )
167 {
168 StreamSocket socket( address.domain() ) ;
169 bool ok = false ;
170 {
171 G::Root claim_root ;
172 ok = socket.canBindHint( address ) ;
173 }
174 if( !ok && do_throw )
175 throw CannotBind( address.displayString() ) ;
176 return ok ;
177 }
178
179 GNet::Server::~Server()
180 {
181 serverCleanup() ;
182 }
183
184 void GNet::Server::serverCleanup()
185 {
186 try
187 {
188 if( ! m_cleaned_up )
189 {
190 m_cleaned_up = true ;
191 serverCleanupCore() ;
192 }
193 }
194 catch(...) // dtor
195 {
196 }
197 }
198
199 void GNet::Server::serverCleanupCore()
200 {
201 for( PeerList::iterator p = m_peer_list.begin() ; p != m_peer_list.end() ; ++p )
202 {
203 ServerPeerHandle handle = *p ;
204 if( handle.peer() != nullptr )
205 {
206 G_DEBUG( "GNet::Server::serverCleanupCore: deleting peer: [" << handle.peer() << "]" ) ;
207 handle.peer()->doDeleteThis(1) ;
208 }
209 }
210 }
211
212 std::pair<bool,GNet::Address> GNet::Server::address() const
213 {
214 std::pair<bool,Address> result( false , Address::defaultAddress() ) ;
215 if( m_socket.get() != nullptr )
216 result = m_socket->getLocalAddress() ;
217 return result ;
218 }
219
220 void GNet::Server::readEvent()
221 {
222 // read-event-on-listening-port => new connection to accept
223
224 G_DEBUG( "GNet::Server::readEvent: " << this ) ;
225 G_ASSERT( m_socket.get() != nullptr ) ;
226
227 // take this opportunity to do garbage collection
228 collectGarbage() ;
229
230 // accept the connection
231 PeerInfo peer_info ;
232 accept( peer_info ) ;
233 G_DEBUG( "GNet::Server::readEvent: new connection from " << peer_info.m_address.displayString()
234 << " on " << peer_info.m_socket->asString() ) ;
235
236 // keep track of peer objects
237 m_peer_list.push_back( ServerPeerHandle() ) ;
238 peer_info.m_handle = &m_peer_list.back() ;
239
240 // create the peer object -- newPeer() implementations will normally catch
241 // their exceptions and return null to avoid terminating the server
242 //
243 ServerPeer * peer = newPeer( peer_info ) ;
244
245 // commit or roll back
246 if( peer == nullptr )
247 {
248 m_peer_list.pop_back() ;
249 G_WARNING( "GNet::Server::readEvent: connection rejected from " << peer_info.m_address.displayString() ) ;
250 }
251 else
252 {
253 m_peer_list.back().set( peer ) ;
254 G_DEBUG( "GNet::Server::readEvent: new connection accepted: " << peer->logId() ) ;
255 }
256 }
257
258 void GNet::Server::accept( PeerInfo & peer_info )
259 {
260 {
261 G::Root claim_root ;
262 AcceptPair accept_pair = m_socket->accept() ;
263 peer_info.m_socket = accept_pair.first ;
264 peer_info.m_address = accept_pair.second ;
265 }
266 G_ASSERT( peer_info.m_socket.get() != nullptr ) ;
267 }
268
269 void GNet::Server::collectGarbage()
270 {
271 // cleanup empty handles, where peer objects have deleted themselves
272 G_DEBUG( "GNet::Server::collectGarbage" ) ;
273 for( PeerList::iterator p = m_peer_list.begin() ; p != m_peer_list.end() ; )
274 {
275 ServerPeerHandle handle = *p ;
276 if( handle.peer() == nullptr )
277 {
278 G_DEBUG( "GNet::Server::collectGarbage: [" << handle.old() << "]" ) ;
279 p = m_peer_list.erase( p ) ;
280 }
281 else
282 {
283 ++p ;
284 }
285 }
286 }
287
288 void GNet::Server::writeEvent()
289 {
290 G_DEBUG( "GNet::Server::writeEvent" ) ;
291 }
292
293 // ===
294
295 GNet::Server::PeerInfo::PeerInfo() :
296 m_address(Address::defaultAddress()) ,
297 m_handle(nullptr)
298 {
299 }
300
301 // ===
302
303 GNet::ServerPeerHandle::ServerPeerHandle() :
304 m_p(nullptr) ,
305 m_old(nullptr)
306 {
307 }
308
309 void GNet::ServerPeerHandle::reset()
310 {
311 m_p = nullptr ;
312 }
313
314 GNet::ServerPeer * GNet::ServerPeerHandle::peer()
315 {
316 return m_p ;
317 }
318
319 GNet::ServerPeer * GNet::ServerPeerHandle::old()
320 {
321 return m_old ;
322 }
323
324 void GNet::ServerPeerHandle::set( ServerPeer * p )
325 {
326 m_p = p ;
327 m_old = p ;
328 }
329
330 /// \file gserver.cpp
GNet::Monitor::removeServerPeer
void removeServerPeer(const Connection &server_peer)
Removes a server connection.
Definition: gmonitor.cpp:142
GNet::ServerPeer
An abstract base class for the GNet::Server's connection to a remote client.
Definition: gserver.h:173
gserver.h
GNet::Server::canBind
static bool canBind(const Address &listening_address, bool do_throw)
Checks that the specified address can be bound.
Definition: gserver.cpp:166
GNet::Server::Server
Server(ExceptionHandler &, const Address &listening_address)
Constructor.
Definition: gserver.cpp:141
GNet::ServerPeer::connectionState
virtual std::string connectionState() const override
Returns the connection state display string.
Definition: gserver.cpp:98
GNet::ServerPeer::ServerPeer
ServerPeer(Server::PeerInfo)
Constructor.
Definition: gserver.cpp:31
GNet::Address
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:54
G::Root
A class which acquires the process's special privileges on construction and releases them on destruct...
Definition: groot.h:49
groot.h
gtest.h
GNet::ServerPeerHandle::set
void set(ServerPeer *p)
Sets the pointer.
Definition: gserver.cpp:324
GNet::ServerPeer::onException
virtual void onException(std::exception &) override
Override from GNet::ExceptionHandler.
Definition: gserver.cpp:134
GNet::ServerPeer::readEvent
virtual void readEvent() override
Override from GNet::EventHandler.
Definition: gserver.cpp:76
GNet::Server::writeEvent
virtual void writeEvent() override
Override from GNet::EventHandler.
Definition: gserver.cpp:288
GNet::ServerPeerHandle
A structure used in the implementation of GNet::Server.
Definition: gserver.h:51
GNet::ExceptionHandler
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket events...
Definition: gexceptionhandler.h:44
GNet::ServerPeer::otherEvent
virtual void otherEvent(EventHandler::Reason) override
Override from GNet::EventHandler.
Definition: gserver.cpp:71
glimits.h
GNet::StreamSocket
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:246
GNet::Address::defaultAddress
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Definition: gaddress_ipv4.cpp:41
GNet::ServerPeer::send
bool send(const std::string &data, std::string::size_type offset=0U)
Sends data down the socket to the peer.
Definition: gserver.cpp:118
gassert.h
GNet::ServerPeer::socket
StreamSocket & socket()
Returns a reference to the client-server connection socket.
Definition: gserver.cpp:65
GNet::StreamSocket::Listener
Overload discriminator class for GNet::StreamSocket.
Definition: gsocket.h:251
GNet::Monitor::instance
static Monitor * instance()
Returns the singleton pointer. Returns null if none.
Definition: gmonitor.cpp:113
GNet::ServerPeer::doDelete
void doDelete(const std::string &=std::string())
Calls onDelete() and schedules a "delete this".
Definition: gserver.cpp:81
GNet::AcceptPair
A class which is used to return a new()ed socket to calling code, together with associated address in...
Definition: gsocket.h:235
GNet::Address::domain
int domain() const
Returns the address 'domain', eg. PF_INET.
Definition: gaddress_ipv4.cpp:184
GNet::Server::~Server
virtual ~Server()
Destructor.
Definition: gserver.cpp:179
GNet::ServerPeer::doDeleteThis
void doDeleteThis(int)
Does delete this. Should only be used by the GNet::Server class.
Definition: gserver.cpp:113
GNet::ServerPeer::peerCertificate
virtual std::string peerCertificate() const override
Returns the peer's TLS certificate.
Definition: gserver.cpp:103
gmonitor.h
GNet::Monitor::addServerPeer
void addServerPeer(const Connection &server_peer)
Adds a server connection.
Definition: gmonitor.cpp:135
GNet::ServerPeerHandle::reset
void reset()
Resets the pointer.
Definition: gserver.cpp:309
GNet::ServerPeer::peerAddress
virtual std::pair< bool, Address > peerAddress() const override
Returns the peer address.
Definition: gserver.cpp:93
GNet::ServerPeerHandle::old
ServerPeer * old()
Returns the pointer value before it was reset().
Definition: gserver.cpp:319
GNet::ServerPeer::writeEvent
virtual void writeEvent() override
Override from GNet::EventHandler.
Definition: gserver.cpp:128
GNet::ServerPeer::logId
std::string logId() const
Returns an identification string for logging purposes.
Definition: gserver.cpp:55
GNet::Server::serverCleanup
void serverCleanup()
May be called from the derived class destructor in order to trigger early deletion of peer objects...
Definition: gserver.cpp:184
GNet::ServerPeer::secureAccept
void secureAccept()
Waits for the peer to start a secure session.
Definition: gserver.cpp:60
GNet::Server::init
void init(const Address &listening_address)
Initilisation after default construction.
Definition: gserver.cpp:153
GNet::ServerPeer::~ServerPeer
virtual ~ServerPeer()
Destructor.
Definition: gserver.cpp:46
GNet::Server::PeerInfo
A structure used in GNet::Server::newPeer().
Definition: gserver.h:85
GNet::ServerPeerHandle::ServerPeerHandle
ServerPeerHandle()
Default constructor.
Definition: gserver.cpp:303
GNet::Server::readEvent
virtual void readEvent() override
Override from GNet::EventHandler.
Definition: gserver.cpp:220
GNet::Address::displayString
std::string displayString() const
Returns a string which represents the transport address for debugging and diagnostics purposes...
Definition: gaddress_ipv4.cpp:129
GNet::Server::address
std::pair< bool, Address > address() const
Returns the listening address.
Definition: gserver.cpp:212
GNet::ServerPeer::localAddress
virtual std::pair< bool, Address > localAddress() const override
Returns the local address.
Definition: gserver.cpp:87
GNet::ServerPeerHandle::peer
ServerPeer * peer()
Returns the pointer.
Definition: gserver.cpp:314
gdebug.h