gmultiserver.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 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 "gnet.h"
23 #include "gmultiserver.h"
24 #include "glog.h"
25 #include "gassert.h"
26 #include "gmemory.h"
27 #include <list>
28 #include <algorithm> // std::swap
29 #include <utility> // std::swap
30 
31 bool GNet::MultiServer::canBind( const AddressList & address_list , bool do_throw )
32 {
33  for( AddressList::const_iterator p = address_list.begin() ; p != address_list.end() ; ++p )
34  {
35  if( ! Server::canBind( *p , do_throw ) )
36  return false ;
37  }
38  return true ;
39 }
40 
42 {
43  AddressList result ;
44  result.push_back( address ) ;
45  return result ;
46 }
47 
49 {
50  AddressList result( list ) ;
51  if( result.empty() )
52  {
53  result.push_back( GNet::Address(port) ) ;
54  }
55  else
56  {
57  for( AddressList::iterator p = result.begin() ; p != result.end() ; ++p )
58  (*p).setPort( port ) ;
59  }
60  return result ;
61 }
62 
64 {
65  AddressList result ;
66  if( list.empty() )
67  {
68  result.push_back( GNet::Address(port) ) ;
69  }
70  else
71  {
72  for( G::Strings::const_iterator p = list.begin() ; p != list.end() ; ++p )
73  {
74  if( (*p).empty() )
75  result.push_back( GNet::Address(port) ) ;
76  else
77  result.push_back( GNet::Address(*p,port) ) ;
78  }
79  }
80  return result ;
81 }
82 
83 GNet::MultiServer::MultiServer( const AddressList & address_list , bool use_connection_lookup )
84 {
85  if( use_connection_lookup )
86  m_connection_lookup <<= new GNet::ConnectionLookup ;
87 
88  G_ASSERT( ! address_list.empty() ) ;
89  for( AddressList::const_iterator p = address_list.begin() ; p != address_list.end() ; ++p )
90  {
91  init( *p , m_connection_lookup.get() ) ;
92  }
93 }
94 
96 {
97 }
98 
99 void GNet::MultiServer::init( const AddressList & address_list )
100 {
101  G_ASSERT( ! address_list.empty() ) ;
102  for( AddressList::const_iterator p = address_list.begin() ; p != address_list.end() ; ++p )
103  {
104  init( *p , NULL ) ;
105  }
106 }
107 
108 void GNet::MultiServer::init( const Address & address , ConnectionLookup * connection_lookup )
109 {
110  // note that the Ptr class does not have proper value semantics...
111  MultiServerPtr ptr( new MultiServerImp(*this,address,connection_lookup) ) ;
112  m_server_list.push_back( MultiServerPtr() ) ; // copy a null pointer into the list
113  m_server_list.back().swap( ptr ) ;
114 }
115 
117 {
118  serverCleanup() ;
119 }
120 
122 {
123  for( List::iterator p = m_server_list.begin() ; p != m_server_list.end() ; ++p )
124  {
125  try
126  {
127  (*p).get()->cleanup() ;
128  }
129  catch(...) // dtor
130  {
131  }
132  }
133 }
134 
135 void GNet::MultiServer::serverReport( const std::string & type ) const
136 {
137  for( List::const_iterator p = m_server_list.begin() ; p != m_server_list.end() ; ++p )
138  {
139  const Server & server = *((*p).get()) ;
140  G_LOG_S( "GNet::MultiServer: " << type << " server on " << server.address().second.displayString() ) ;
141  }
142 }
143 
144 std::pair<bool,GNet::Address> GNet::MultiServer::firstAddress() const
145 {
146  std::pair<bool,GNet::Address> result( false , GNet::Address::invalidAddress() ) ;
147  for( List::const_iterator p = m_server_list.begin() ; p != m_server_list.end() ; ++p )
148  {
149  if( (*p).get()->address().first )
150  {
151  result.first = true ;
152  result.second = (*p).get()->address().second ;
153  break ;
154  }
155  }
156  return result ;
157 }
158 
159 // ==
160 
162  ConnectionLookup * connection_lookup ) :
163  Server(address,connection_lookup) ,
164  m_ms(ms)
165 {
166 }
167 
169 {
170  return m_ms.newPeer( peer_info ) ;
171 }
172 
174 {
175  serverCleanup() ;
176 }
177 
178 // ==
179 
181  m_p(p)
182 {
183 }
184 
186  m_p(other.m_p)
187 {
188 }
189 
191 {
192  delete m_p ;
193 }
194 
196 {
197  m_p = rhs.m_p ;
198 }
199 
201 {
202  std::swap( other.m_p , m_p ) ;
203 }
204 
206 {
207  return m_p ;
208 }
209 
211 {
212  return m_p ;
213 }
214 
MultiServerPtr(ServerImp *=NULL)
Constructor.
#define G_LOG_S(expr)
Definition: glog.h:103
static AddressList addressList(const Address &)
A trivial convenience fuction that returns the given addresses as a single-element list...
An abstract base class for the GNet::Server's connection to a remote client.
Definition: gserver.h:191
static bool canBind(const Address &listening_address, bool do_throw)
Checks that the specified address can be bound.
Definition: gserver.cpp:172
A private implementation class used by GNet::MultiServer.
Definition: gmultiserver.h:68
MultiServer()
Default constructor. Initialise with init().
void swap(MultiServerPtr &)
Swaps internals with the other.
std::list< std::string > Strings
A std::list of std::strings.
Definition: gstrings.h:39
MultiServerImp * get()
Returns the raw pointer.
The Address class encapsulates an IP transport address.
Definition: gaddress.h:48
static Address invalidAddress()
Returns an invalid address.
A class for getting more information about a connection from the operating system.
A network server class which listens on a specific port and spins off ServerPeer objects for each inc...
Definition: gserver.h:83
virtual ServerPeer * newPeer(PeerInfo)
Server peer factory method.
static bool canBind(const AddressList &listening_address_list, bool do_throw)
Checks that the specified addresses can be bound.
#define G_ASSERT(test)
Definition: gassert.h:30
void cleanup()
Does cleanup.
virtual ~MultiServer()
Destructor.
A private implementation class used by GNet::MultiServer.
Definition: gmultiserver.h:43
void init(const AddressList &address_list)
Initilisation after default construction.
MultiServerImp(MultiServer &ms, const Address &, ConnectionLookup *)
Constructor.
std::list< Address > AddressList
Definition: gmultiserver.h:105
void serverCleanup()
Should be called from all derived classes' destructors so that peer objects can use their Server obje...
~MultiServerPtr()
Destructor.
A server that listens on more than one interface using a facade pattern to multiple Server instances...
Definition: gmultiserver.h:102
std::pair< bool, Address > firstAddress() const
Returns the first listening address.
A structure used in GNet::Server::newPeer().
Definition: gserver.h:91
std::pair< bool, Address > address() const
Returns the listening address.
Definition: gserver.cpp:221
void serverReport(const std::string &server_type) const
Writes to the system log a summary of the underlying server objects and their addresses.
void operator=(const MultiServerPtr &)
Assignment operator.