E-MailRelay
gmultiserver.h
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 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 using AddressList = std::vector<Address> ;
53
54 struct ServerInfo /// A structure used in GNet::MultiServer::newPeer().
55 {
56 ServerInfo() ;
57 Address m_address ; ///< The server address that the peer connected to.
58 } ;
59
60 MultiServer( EventState es_listener , const G::StringArray & listen_list ,
61 unsigned int port , const std::string & server_type ,
62 ServerPeer::Config server_peer_config , Server::Config server_config ) ;
63 ///< Constructor. The server listens on inherited file descriptors
64 ///< formatted like "fd#3", specific local addresses (eg. "127.0.0.1")
65 ///< and addresses from named interfaces ("eth0").
66 ///<
67 ///< Listens on "0.0.0.0" and "::" if the listen list is
68 ///< empty.
69 ///<
70 ///< Throws if there are no addresses in the list and the
71 ///< GNet::Interfaces implementation is not active().
72
73 ~MultiServer() override ;
74 ///< Destructor.
75
76 bool hasPeers() const ;
77 ///< Returns true if peers() is not empty.
78
79 std::vector<std::weak_ptr<ServerPeer>> peers() ;
80 ///< Returns the list of ServerPeer-derived objects.
81 ///< The returned ServerPeer objects must not outlive
82 ///< this MultiServer.
83
84 std::unique_ptr<ServerPeer> doNewPeer( EventStateUnbound , ServerPeerInfo && , const ServerInfo & ) ;
85 ///< Pseudo-private method used by the pimple class.
86
87protected:
88 virtual std::unique_ptr<ServerPeer> newPeer( EventStateUnbound , ServerPeerInfo && , ServerInfo ) = 0 ;
89 ///< A factory method which creates a ServerPeer-derived
90 ///< object. See GNet::Server for the details.
91
92 void serverCleanup() ;
93 ///< Should be called from all derived classes' destructors
94 ///< so that peer objects can use their Server objects
95 ///< safely during their own destruction.
96
97 void serverReport( const std::string & group = {} ) const ;
98 ///< Writes to the system log a summary of the underlying server
99 ///< objects and their addresses.
100
101private: // overrides
102 void onInterfaceEvent( const std::string & ) override ; // GNet::InterfacesHandler
103
104public:
105 MultiServer( const MultiServer & ) = delete ;
106 MultiServer( MultiServer && ) = delete ;
107 MultiServer & operator=( const MultiServer & ) = delete ;
108 MultiServer & operator=( MultiServer && ) = delete ;
109
110private:
111 using ServerPtr = std::unique_ptr<MultiServerImp> ;
112 using ServerList = std::vector<ServerPtr> ;
113 bool gotServerFor( Address ) const ;
114 bool gotAddressFor( const Listener & , const AddressList & ) const ;
115 void onInterfaceEventTimeout() ;
116 static bool match( const Address & , const Address & ) ;
117 static std::string displayString( const Address & ) ;
118 void createServer( Descriptor ) ;
119 void createServer( const Address & , bool ) ;
120 void createServer( const Address & , bool , std::nothrow_t ) ;
121 ServerList::iterator removeServer( ServerList::iterator ) ;
122
123private:
124 EventState m_es ;
125 G::StringArray m_listener_list ;
126 unsigned int m_port ;
127 std::string m_server_type ;
128 ServerPeer::Config m_server_peer_config ;
129 Server::Config m_server_config ;
130 Interfaces m_if ;
131 ServerList m_server_list ;
132 Timer<MultiServer> m_interface_event_timer ;
133} ;
134
135//| \class GNet::MultiServerImp
136/// A GNet::Server class used in GNet::MultiServer.
137///
138class GNet::MultiServerImp : public GNet::Server
139{
140public:
141 MultiServerImp( MultiServer & , EventState , bool fixed , const Address & , ServerPeer::Config , Server::Config ) ;
142 ///< Constructor.
143
144 MultiServerImp( MultiServer & , EventState , Descriptor , ServerPeer::Config , Server::Config ) ;
145 ///< Constructor.
146
147 ~MultiServerImp() override ;
148 ///< Destructor.
149
150 std::unique_ptr<ServerPeer> newPeer( EventStateUnbound , ServerPeerInfo&& ) final ;
151 ///< Called by the base class to create a new ServerPeer.
152
153 void cleanup() ;
154 ///< Calls GNet::Server::serverCleanup().
155
156 bool dynamic() const ;
157 ///< Returns true if not a fixed address, as passed in to ctor.
158
159public:
160 MultiServerImp( const MultiServerImp & ) = delete ;
161 MultiServerImp( MultiServerImp && ) = delete ;
162 MultiServerImp & operator=( const MultiServerImp & ) = delete ;
163 MultiServerImp & operator=( MultiServerImp && ) = delete ;
164
165private:
166 MultiServer & m_ms ;
167 bool m_fixed ;
168} ;
169
170#endif
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:63
A class that encapsulates a network socket file descriptor and an associated windows event handle.
Definition: gdescriptor.h:37
The EventStateUnbound class is used as a device to force factory methods to plumb-in an ExceptionSour...
Definition: geventstate.h:231
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
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.
virtual std::unique_ptr< ServerPeer > newPeer(EventStateUnbound, ServerPeerInfo &&, ServerInfo)=0
A factory method which creates a ServerPeer-derived object.
std::unique_ptr< ServerPeer > doNewPeer(EventStateUnbound, ServerPeerInfo &&, const ServerInfo &)
Pseudo-private method used by the pimple class.
void serverReport(const std::string &group={}) const
Writes to the system log a summary of the underlying server objects and their addresses.
MultiServer(EventState es_listener, const G::StringArray &listen_list, unsigned int port, const std::string &server_type, ServerPeer::Config server_peer_config, Server::Config server_config)
Constructor.
void serverCleanup()
Should be called from all derived classes' destructors so that peer objects can use their Server obje...
A move-only structure used in GNet::Server::newPeer() and containing the new socket.
Definition: gserver.h:142
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(EventStateUnbound, 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:1243
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84
A structure used in GNet::MultiServer::newPeer().
Definition: gmultiserver.h:55
Address m_address
The server address that the peer connected to.
Definition: gmultiserver.h:57
A configuration structure for GNet::ServerPeer.
Definition: gserverpeer.h:64
A configuration structure for GNet::Server.
Definition: gserver.h:56