E-MailRelay
gserver.h
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 gserver.h
19///
20
21#ifndef G_NET_SERVER_H
22#define G_NET_SERVER_H
23
24#include "gdef.h"
25#include "ggettext.h"
26#include "gserverpeer.h"
27#include "gexceptionsink.h"
28#include "gexception.h"
29#include "gsocket.h"
30#include "glistener.h"
31#include "glimits.h"
32#include "gprocess.h"
33#include "gevent.h"
34#include <utility>
35#include <memory>
36#include <string>
37
38namespace GNet
39{
40 class Server ;
41 class ServerPeer ;
42 class ServerPeerInfo ;
43}
44
45//| \class GNet::Server
46/// A network server class which listens on a specific port and spins off
47/// ServerPeer objects for each incoming connection.
48/// \see GNet::ServerPeer
49///
50class GNet::Server : public Listener, private EventHandler, private ExceptionHandler
51{
52public:
53 G_EXCEPTION( CannotBind , tx("cannot bind the listening port") ) ;
54
55 struct Config /// A configuration structure for GNet::Server.
56 {
57 StreamSocket::Config stream_socket_config ;
58 bool uds_open_permissions {false} ;
59 Config & set_stream_socket_config( const StreamSocket::Config & ) ;
60 Config & set_uds_open_permissions( bool b = true ) noexcept ;
61 } ;
62
63 Server( ExceptionSink , const Address & listening_address , const ServerPeer::Config & , const Config & ) ;
64 ///< Constructor. The server listens on the given address,
65 ///< which can be the 'any' address. The ExceptionSink
66 ///< is used for exceptions relating to the listening
67 ///< socket, not the server peers.
68
69 Server( ExceptionSink , Descriptor listening_fd , const ServerPeer::Config & , const Config & ) ;
70 ///< Constructor overload for adopting an externally-managed
71 ///< listening file descriptor.
72
73 ~Server() override ;
74 ///< Destructor.
75
76 Address address() const override ;
77 ///< Returns the listening address.
78 ///< Override from GNet::Listener.
79
80 std::vector<std::weak_ptr<GNet::ServerPeer>> peers() ;
81 ///< Returns the list of ServerPeer objects.
82
83 bool hasPeers() const ;
84 ///< Returns true if peers() is not empty.
85
86protected:
87 virtual std::unique_ptr<ServerPeer> newPeer( ExceptionSinkUnbound , ServerPeerInfo && ) = 0 ;
88 ///< A factory method which new()s a ServerPeer-derived
89 ///< object. This method is called when a new connection
90 ///< comes in to this server. The new ServerPeer object
91 ///< is used to represent the state of the client/server
92 ///< connection.
93 ///<
94 ///< The implementation should std::move the 'ServerPeerInfo'
95 ///< parameter through to the ServerPeer base-class
96 ///< constructor.
97 ///<
98 ///< The implementation should return nullptr for non-fatal
99 ///< errors. It is expected that a typical server process will
100 ///< terminate if newPeer() throws, so most implementations
101 ///< will catch any exceptions and return nullptr.
102
103 void serverCleanup() ;
104 ///< Should be called by the most-derived class's
105 ///< destructor in order to trigger early deletion of
106 ///< peer objects before the derived part of the server
107 ///< disappears. This prevents slicing if the destructor
108 ///< of the most-derived ServerPeer makes use of the
109 ///< most-derived Server.
110
111private: // overrides
112 void readEvent() override ; // Override from GNet::EventHandler.
113 void writeEvent() override ; // Override from GNet::EventHandler.
114 void onException( ExceptionSource * , std::exception & , bool ) override ; // Override from GNet::ExceptionHandler.
115
116public:
117 Server( const Server & ) = delete ;
118 Server( Server && ) = delete ;
119 Server & operator=( const Server & ) = delete ;
120 Server & operator=( Server && ) = delete ;
121
122private:
123 void accept( ServerPeerInfo & ) ;
124 static bool unlink( G::SignalSafe , const char * ) noexcept ;
125
126private:
127 using PeerList = std::vector<std::shared_ptr<ServerPeer>> ;
128 ExceptionSink m_es ;
129 Config m_config ;
130 ServerPeer::Config m_server_peer_config ;
131 StreamSocket m_socket ; // listening socket
132 PeerList m_peer_list ;
133} ;
134
135//| \class GNet::ServerPeerInfo
136/// A move-only structure used in GNet::Server::newPeer() and
137/// containing the new socket.
138///
140{
141public:
142 std::unique_ptr<StreamSocket> m_socket ;
143 Address m_address ;
144 ServerPeer::Config m_server_peer_config ;
145 Server * m_server ;
147} ;
148
149inline GNet::Server::Config & GNet::Server::Config::set_stream_socket_config( const StreamSocket::Config & c ) { stream_socket_config = c ; return *this ; }
150inline GNet::Server::Config & GNet::Server::Config::set_uds_open_permissions( bool b ) noexcept { uds_open_permissions = b ; return *this ; }
151
152#endif
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:62
A class that encapsulates a network socket file descriptor and an associated windows event handle.
Definition: gdescriptor.h:37
A base class for classes that have a file descriptor and handle asynchronous events from the event lo...
Definition: geventhandler.h:48
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket/future event...
A potential ExceptionSink that is realised by bind()ing an exception source pointer.
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
A mixin base class that identifies the source of an exception when delivered to GNet::ExceptionHandle...
An interface for a network listener.
Definition: glistener.h:37
A move-only structure used in GNet::Server::newPeer() and containing the new socket.
Definition: gserver.h:140
A network server class which listens on a specific port and spins off ServerPeer objects for each inc...
Definition: gserver.h:51
~Server() override
Destructor.
Definition: gserver.cpp:86
Address address() const override
Returns the listening address.
Definition: gserver.cpp:91
Server(ExceptionSink, const Address &listening_address, const ServerPeer::Config &, const Config &)
Constructor.
Definition: gserver.cpp:47
bool hasPeers() const
Returns true if peers() is not empty.
Definition: gserver.cpp:182
virtual std::unique_ptr< ServerPeer > newPeer(ExceptionSinkUnbound, ServerPeerInfo &&)=0
A factory method which new()s a ServerPeer-derived object.
std::vector< std::weak_ptr< GNet::ServerPeer > > peers()
Returns the list of ServerPeer objects.
Definition: gserver.cpp:187
void serverCleanup()
Should be called by the most-derived class's destructor in order to trigger early deletion of peer ob...
Definition: gserver.cpp:177
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:341
An empty structure that is used to indicate a signal-safe, reentrant implementation.
Definition: gsignalsafe.h:37
Network classes.
Definition: gdef.h:1144
constexpr const char * tx(const char *p)
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84
A configuration structure for GNet::ServerPeer.
Definition: gserverpeer.h:63
A configuration structure for GNet::Server.
Definition: gserver.h:56
A configuration structure for GNet::StreamSocket.
Definition: gsocket.h:348