E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gmultiserver.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 // gmultiserver.cpp
19 //
20
21 #include "gdef.h"
22 #include "gmultiserver.h"
23 #include "glog.h"
24 #include "gassert.h"
25 #include <list>
26 #include <algorithm> // std::swap
27 #include <utility> // std::swap
28
29 GNet::MultiServer::MultiServer( ExceptionHandler & eh , const AddressList & address_list ) :
30 m_eh(eh)
31 {
32 G_ASSERT( ! address_list.empty() ) ;
33 init( address_list ) ;
34 }
35
36 GNet::MultiServer::MultiServer( ExceptionHandler & eh ) :
37 m_eh(eh)
38 {
39 }
40
41 GNet::MultiServer::~MultiServer()
42 {
43 serverCleanup() ;
44 }
45
46 void GNet::MultiServer::init( const AddressList & address_list )
47 {
48 G_ASSERT( ! address_list.empty() ) ;
49 for( AddressList::const_iterator p = address_list.begin() ; p != address_list.end() ; ++p )
50 {
51 init( *p ) ;
52 }
53 }
54
55 void GNet::MultiServer::init( const Address & address )
56 {
57 // note that the Ptr class does not have proper value semantics...
58 MultiServerPtr ptr( new MultiServerImp(*this,m_eh,address) ) ;
59 m_server_list.push_back( MultiServerPtr() ) ; // copy a null pointer into the list
60 m_server_list.back().swap( ptr ) ;
61 }
62
63 bool GNet::MultiServer::canBind( const AddressList & address_list , bool do_throw )
64 {
65 for( AddressList::const_iterator p = address_list.begin() ; p != address_list.end() ; ++p )
66 {
67 if( ! Server::canBind( *p , do_throw ) )
68 return false ;
69 }
70 return true ;
71 }
72
73 GNet::MultiServer::AddressList GNet::MultiServer::addressList( const Address & address )
74 {
75 AddressList result ;
76 result.reserve( 1U ) ;
77 result.push_back( address ) ;
78 return result ;
79 }
80
81 GNet::MultiServer::AddressList GNet::MultiServer::addressList( const AddressList & list , unsigned int port )
82 {
83 AddressList result ;
84 if( list.empty() )
85 {
86 result.reserve( 2U ) ;
87 if( Address::supports(Address::Family::ipv4()) ) result.push_back( Address(Address::Family::ipv4(),port) ) ;
88 if( Address::supports(Address::Family::ipv6()) ) result.push_back( Address(Address::Family::ipv6(),port) ) ;
89 }
90 else
91 {
92 result = list ;
93 for( AddressList::iterator p = result.begin() ; p != result.end() ; ++p )
94 (*p).setPort( port ) ;
95 }
96 return result ;
97 }
98
99 GNet::MultiServer::AddressList GNet::MultiServer::addressList( const G::StringArray & list , unsigned int port )
100 {
101 AddressList result ;
102 if( list.empty() )
103 {
104 result.reserve( 2U ) ;
105 if( Address::supports(Address::Family::ipv4()) ) result.push_back( Address(Address::Family::ipv4(),port) ) ;
106 if( Address::supports(Address::Family::ipv6()) ) result.push_back( Address(Address::Family::ipv6(),port) ) ;
107 }
108 else
109 {
110 result.reserve( list.size() ) ;
111 for( G::StringArray::const_iterator p = list.begin() ; p != list.end() ; ++p )
112 {
113 const bool is_inaddrany = (*p).empty() ;
114 if( is_inaddrany )
115 {
116 if( Address::supports(Address::Family::ipv4()) ) result.push_back( Address(Address::Family::ipv4(),port) ) ;
117 if( Address::supports(Address::Family::ipv6()) ) result.push_back( Address(Address::Family::ipv6(),port) ) ; // moot
118 }
119 else
120 {
121 result.push_back( Address(*p,port) ) ;
122 }
123 }
124 }
125 return result ;
126 }
127
128 void GNet::MultiServer::serverCleanup()
129 {
130 for( List::iterator p = m_server_list.begin() ; p != m_server_list.end() ; ++p )
131 {
132 try
133 {
134 (*p).get()->cleanup() ;
135 }
136 catch(...) // dtor
137 {
138 }
139 }
140 }
141
142 void GNet::MultiServer::serverReport( const std::string & type ) const
143 {
144 for( List::const_iterator p = m_server_list.begin() ; p != m_server_list.end() ; ++p )
145 {
146 const Server & server = *((*p).get()) ;
147 G_LOG_S( "GNet::MultiServer: " << type << " server on " << server.address().second.displayString() ) ;
148 }
149 }
150
151 std::pair<bool,GNet::Address> GNet::MultiServer::firstAddress() const
152 {
153 std::pair<bool,Address> result( false , Address::defaultAddress() ) ;
154 for( List::const_iterator p = m_server_list.begin() ; p != m_server_list.end() ; ++p )
155 {
156 if( (*p).get()->address().first )
157 {
158 result.first = true ;
159 result.second = (*p).get()->address().second ;
160 break ;
161 }
162 }
163 return result ;
164 }
165
166 // ==
167
168 GNet::MultiServerImp::MultiServerImp( MultiServer & ms , ExceptionHandler & eh , const Address & address ) :
169 Server(eh,address) ,
170 m_ms(ms)
171 {
172 }
173
174 GNet::ServerPeer * GNet::MultiServerImp::newPeer( PeerInfo peer_info )
175 {
176 MultiServer::ServerInfo server_info ;
177 server_info.m_address = address().first ? address().second : Address::defaultAddress() ;
178 return m_ms.newPeer( peer_info , server_info ) ;
179 }
180
181 void GNet::MultiServerImp::cleanup()
182 {
183 serverCleanup() ;
184 }
185
186 // ==
187
188 GNet::MultiServerPtr::MultiServerPtr( ServerImp * p ) :
189 m_p(p)
190 {
191 }
192
193 GNet::MultiServerPtr::MultiServerPtr( const MultiServerPtr & other ) :
194 m_p(other.m_p)
195 {
196 }
197
198 GNet::MultiServerPtr::~MultiServerPtr()
199 {
200 delete m_p ;
201 }
202
203 void GNet::MultiServerPtr::operator=( const MultiServerPtr & rhs )
204 {
205 m_p = rhs.m_p ;
206 }
207
208 void GNet::MultiServerPtr::swap( MultiServerPtr & other )
209 {
210 std::swap( other.m_p , m_p ) ;
211 }
212
213 GNet::MultiServerImp * GNet::MultiServerPtr::get()
214 {
215 return m_p ;
216 }
217
218 const GNet::MultiServerImp * GNet::MultiServerPtr::get() const
219 {
220 return m_p ;
221 }
222
223 // ==
224
225 GNet::MultiServer::ServerInfo::ServerInfo() :
226 m_address(Address::defaultAddress())
227 {
228 }
229
230 /// \file gmultiserver.cpp
GNet::MultiServer::addressList
static AddressList addressList(const Address &)
A trivial convenience fuction that returns the given address as a single-element list.
Definition: gmultiserver.cpp:73
GNet::ServerPeer
An abstract base class for the GNet::Server's connection to a remote client.
Definition: gserver.h:173
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::MultiServerPtr
A private implementation class used by GNet::MultiServer.
Definition: gmultiserver.h:60
glog.h
GNet::MultiServerPtr::swap
void swap(MultiServerPtr &)
Swaps internals with the other.
Definition: gmultiserver.cpp:208
GNet::MultiServerPtr::get
MultiServerImp * get()
Returns the raw pointer.
Definition: gmultiserver.cpp:213
GNet::Address
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:54
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
GNet::MultiServerImp::MultiServerImp
MultiServerImp(MultiServer &, ExceptionHandler &, const Address &)
Constructor.
Definition: gmultiserver.cpp:168
gmultiserver.h
GNet::Server
A network server class which listens on a specific port and spins off ServerPeer objects for each inc...
Definition: gserver.h:80
GNet::ExceptionHandler
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket events...
Definition: gexceptionhandler.h:44
GNet::MultiServer::canBind
static bool canBind(const AddressList &listening_address_list, bool do_throw)
Checks that the specified addresses can be bound.
Definition: gmultiserver.cpp:63
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
gassert.h
GNet::MultiServerImp::cleanup
void cleanup()
Does cleanup.
Definition: gmultiserver.cpp:181
GNet::MultiServer::ServerInfo
A structure used in GNet::MultiServer::newPeer().
Definition: gmultiserver.h:100
GNet::MultiServer::~MultiServer
virtual ~MultiServer()
Destructor.
Definition: gmultiserver.cpp:41
GNet::MultiServerImp
A private implementation class used by GNet::MultiServer.
Definition: gmultiserver.h:39
GNet::MultiServerPtr::MultiServerPtr
MultiServerPtr(ServerImp *=nullptr)
Constructor.
Definition: gmultiserver.cpp:188
GNet::MultiServer::init
void init(const AddressList &address_list)
Initilisation after default construction.
Definition: gmultiserver.cpp:46
GNet::MultiServer::serverCleanup
void serverCleanup()
Should be called from all derived classes' destructors so that peer objects can use their Server obje...
Definition: gmultiserver.cpp:128
GNet::MultiServerPtr::~MultiServerPtr
~MultiServerPtr()
Destructor.
Definition: gmultiserver.cpp:198
GNet::MultiServer
A server that listens on more than one interface using a facade pattern to multiple GNet::Server inst...
Definition: gmultiserver.h:94
GNet::MultiServer::ServerInfo::m_address
Address m_address
The server address that the peer connected to.
Definition: gmultiserver.h:102
GNet::MultiServer::firstAddress
std::pair< bool, Address > firstAddress() const
Returns the first listening address.
Definition: gmultiserver.cpp:151
GNet::MultiServer::MultiServer
MultiServer(ExceptionHandler &, const AddressList &address_list)
Constructor.
Definition: gmultiserver.cpp:29
GNet::Address::supports
static bool supports(Family)
Returns true if the implementation supports the given address family.
Definition: gaddress_ipv4.cpp:36
GNet::Server::address
std::pair< bool, Address > address() const
Returns the listening address.
Definition: gserver.cpp:212
GNet::MultiServer::serverReport
void serverReport(const std::string &server_type) const
Writes to the system log a summary of the underlying server objects and their addresses.
Definition: gmultiserver.cpp:142
GNet::MultiServerPtr::operator=
void operator=(const MultiServerPtr &)
Assignment operator.
Definition: gmultiserver.cpp:203