E-MailRelay
gmultiserver.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 gmultiserver.h
19///
20
21#ifndef G_NET_MULTISERVER_H
22#define G_NET_MULTISERVER_H
23
24#include "gdef.h"
25#include "gevent.h"
26#include "gserver.h"
27#include "gtimer.h"
28#include "ginterfaces.h"
29#include "gexception.h"
30#include <memory>
31#include <utility> // std::pair<>
32#include <vector>
33#include <new> // std::nothrow_t
34
35namespace GNet
36{
37 class MultiServer ;
38 class MultiServerImp ;
39}
40
41//| \class GNet::MultiServer
42/// A server that listens on more than one address using a facade
43/// pattern to multiple GNet::Server instances. Supports dynamic
44/// server instantiation based on available network interface
45/// addresses (see GNet::InterfacesHandler).
46///
48{
49public:
50 G_EXCEPTION( NoListeningAddresses , tx("no listening addresses") ) ;
51 G_EXCEPTION( InvalidName , tx("invalid address or interface name") ) ;
52 G_EXCEPTION( InvalidFd , tx("invalid listening file descriptor number") ) ;
53 using AddressList = std::vector<Address> ;
54
55 struct ServerInfo /// A structure used in GNet::MultiServer::newPeer().
56 {
57 ServerInfo() ;
58 Address m_address ; ///< The server address that the peer connected to.
59 } ;
60
61 MultiServer( ExceptionSink listener_exception_sink , const G::StringArray & listen_list ,
62 unsigned int port , const std::string & server_type ,
63 ServerPeer::Config server_peer_config , Server::Config server_config ) ;
64 ///< Constructor. The server listens on inherited file descriptors
65 ///< formatted like "#3", specific local addresses (eg. "127.0.0.1")
66 ///< and addresses from named interfaces ("eth0").
67 ///<
68 ///< Listens on "0.0.0.0" and "::" if the listen list is
69 ///< empty.
70 ///<
71 ///< Throws if there are no addresses in the list and the
72 ///< GNet::Interfaces implementation is not active().
73
74 ~MultiServer() override ;
75 ///< Destructor.
76
77 bool hasPeers() const ;
78 ///< Returns true if peers() is not empty.
79
80 std::vector<std::weak_ptr<ServerPeer>> peers() ;
81 ///< Returns the list of ServerPeer-derived objects.
82
83 std::unique_ptr<ServerPeer> doNewPeer( ExceptionSinkUnbound , ServerPeerInfo && , const ServerInfo & ) ;
84 ///< Pseudo-private method used by the pimple class.
85
86protected:
87 virtual std::unique_ptr<ServerPeer> newPeer( ExceptionSinkUnbound , ServerPeerInfo && , ServerInfo ) = 0 ;
88 ///< A factory method which creates a ServerPeer-derived
89 ///< object. See GNet::Server for the details.
90
91 void serverCleanup() ;
92 ///< Should be called from all derived classes' destructors
93 ///< so that peer objects can use their Server objects
94 ///< safely during their own destruction.
95
96 void serverReport( const std::string & group = {} ) const ;
97 ///< Writes to the system log a summary of the underlying server
98 ///< objects and their addresses.
99
100private: // overrides
101 void onInterfaceEvent( const std::string & ) override ; // GNet::InterfacesHandler
102
103public:
104 MultiServer( const MultiServer & ) = delete ;
105 MultiServer( MultiServer && ) = delete ;
106 MultiServer & operator=( const MultiServer & ) = delete ;
107 MultiServer & operator=( MultiServer && ) = delete ;
108
109private:
110 using ServerPtr = std::unique_ptr<MultiServerImp> ;
111 using ServerList = std::vector<ServerPtr> ;
112 bool gotServerFor( Address ) const ;
113 bool gotAddressFor( const Listener & , const AddressList & ) const ;
114 void onInterfaceEventTimeout() ;
115 static bool match( const Address & , const Address & ) ;
116 static std::string displayString( const Address & ) ;
117 void createServer( Descriptor ) ;
118 void createServer( const Address & , bool ) ;
119 void createServer( const Address & , bool , std::nothrow_t ) ;
120 ServerList::iterator removeServer( ServerList::iterator ) ;
121
122private:
123 ExceptionSink m_es ;
124 G::StringArray m_listener_list ;
125 unsigned int m_port ;
126 std::string m_server_type ;
127 ServerPeer::Config m_server_peer_config ;
128 Server::Config m_server_config ;
129 Interfaces m_if ;
130 ServerList m_server_list ;
131 Timer<MultiServer> m_interface_event_timer ;
132} ;
133
134//| \class GNet::MultiServerImp
135/// A GNet::Server class used in GNet::MultiServer.
136///
137class GNet::MultiServerImp : public GNet::Server
138{
139public:
140 MultiServerImp( MultiServer & , ExceptionSink , bool fixed , const Address & , ServerPeer::Config , Server::Config ) ;
141 ///< Constructor.
142
143 MultiServerImp( MultiServer & , ExceptionSink , Descriptor , ServerPeer::Config , Server::Config ) ;
144 ///< Constructor.
145
146 ~MultiServerImp() override ;
147 ///< Destructor.
148
149 std::unique_ptr<ServerPeer> newPeer( ExceptionSinkUnbound , ServerPeerInfo&& ) final ;
150 ///< Called by the base class to create a new ServerPeer.
151
152 void cleanup() ;
153 ///< Calls GNet::Server::serverCleanup().
154
155 bool dynamic() const ;
156 ///< Returns true if not a fixed address, as passed in to ctor.
157
158public:
159 MultiServerImp( const MultiServerImp & ) = delete ;
160 MultiServerImp( MultiServerImp && ) = delete ;
161 MultiServerImp & operator=( const MultiServerImp & ) = delete ;
162 MultiServerImp & operator=( MultiServerImp && ) = delete ;
163
164private:
165 MultiServer & m_ms ;
166 bool m_fixed ;
167} ;
168
169#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 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.
An interface for receiving notification of network changes.
Definition: ginterfaces.h:137
A class for getting a list of network interfaces and their addresses.
Definition: ginterfaces.h:48
An interface for a network listener.
Definition: glistener.h:37
A server that listens on more than one address using a facade pattern to multiple GNet::Server instan...
Definition: gmultiserver.h:48
~MultiServer() override
Destructor.
bool hasPeers() const
Returns true if peers() is not empty.
std::vector< std::weak_ptr< ServerPeer > > peers()
Returns the list of ServerPeer-derived objects.
MultiServer(ExceptionSink listener_exception_sink, const G::StringArray &listen_list, unsigned int port, const std::string &server_type, ServerPeer::Config server_peer_config, Server::Config server_config)
Constructor.
void serverReport(const std::string &group={}) const
Writes to the system log a summary of the underlying server objects and their addresses.
std::unique_ptr< ServerPeer > doNewPeer(ExceptionSinkUnbound, ServerPeerInfo &&, const ServerInfo &)
Pseudo-private method used by the pimple class.
void serverCleanup()
Should be called from all derived classes' destructors so that peer objects can use their Server obje...
virtual std::unique_ptr< ServerPeer > newPeer(ExceptionSinkUnbound, ServerPeerInfo &&, ServerInfo)=0
A factory method which creates a ServerPeer-derived object.
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
virtual std::unique_ptr< ServerPeer > newPeer(ExceptionSinkUnbound, ServerPeerInfo &&)=0
A factory method which new()s a ServerPeer-derived object.
A timer class template in which the timeout is delivered to the specified method.
Definition: gtimer.h:141
Network classes.
Definition: gdef.h:1144
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
constexpr const char * tx(const char *p)
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84
A structure used in GNet::MultiServer::newPeer().
Definition: gmultiserver.h:56
Address m_address
The server address that the peer connected to.
Definition: gmultiserver.h:58
A configuration structure for GNet::ServerPeer.
Definition: gserverpeer.h:63
A configuration structure for GNet::Server.
Definition: gserver.h:56