gmonitor.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 // gmonitor.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gnet.h"
23 #include "glimits.h"
24 #include "gmonitor.h"
25 #include "gstr.h"
26 #include "gassert.h"
27 #include <map>
28 #include <deque>
29 #include <algorithm> // std::swap
30 #include <utility> // std::swap
31 
36 {
37 public:
38  explicit MonitorImp( Monitor & monitor ) ;
39  void add( const Connection & , bool is_client ) ;
40  void remove( const Connection & , bool is_client ) ;
41  void report( std::ostream & s , const std::string & px , const std::string & eol ) const ;
42  std::string certificateId( const std::string & certificiate ) ;
43  std::pair<std::string,bool> findCertificate( const std::string & certificate ) ;
44 
45 private:
46  struct ConnectionInfo
47  {
48  bool is_client ;
49  explicit ConnectionInfo( bool is_client_ ) : is_client(is_client_) {}
50  } ;
51  struct CertificateInfo
52  {
53  std::string certificate ;
54  int id ;
55  CertificateInfo( const std::string & c , int id_ ) : certificate(c) , id(id_) {}
56  bool match( std::string s ) const { return s == certificate ; }
57  } ;
58  struct CertificateMatch
59  {
60  const std::string & m_s ;
61  explicit CertificateMatch( const std::string & s ) : m_s(s) {}
62  bool operator()( const CertificateInfo & o ) const { return o.match(m_s) ; }
63  } ;
64  typedef std::map<const Connection*,ConnectionInfo> ConnectionMap ;
65  typedef std::deque<CertificateInfo> Certificates ;
66  ConnectionMap m_connections ;
67  Certificates m_certificates ;
68  int m_id_generator ;
69  unsigned long m_client_adds ;
70  unsigned long m_client_removes ;
71  unsigned long m_server_peer_adds ;
72  unsigned long m_server_peer_removes ;
73 } ;
74 
76  m_id_generator(0) ,
77  m_client_adds(0UL) ,
78  m_client_removes(0UL) ,
79  m_server_peer_adds(0UL) ,
80  m_server_peer_removes(0UL)
81 {
82 }
83 
84 // ===
85 
86 GNet::Monitor * & GNet::Monitor::pthis()
87 {
88  static GNet::Monitor * p = NULL ;
89  return p ;
90 }
91 
93  m_imp( new MonitorImp(*this) )
94 {
95  G_ASSERT( pthis() == NULL ) ;
96  pthis() = this ;
97 }
98 
100 {
101  delete m_imp ;
102  pthis() = NULL ;
103 }
104 
106 {
107  return pthis() ;
108 }
109 
111 {
112  return m_signal ;
113 }
114 
115 void GNet::Monitor::addClient( const Connection & client )
116 {
117  m_imp->add( client , true ) ;
118  m_signal.emit( "out" , "start" ) ;
119 }
120 
122 {
123  m_imp->remove( client , true ) ;
124  m_signal.emit( "out" , "end" ) ;
125 }
126 
127 void GNet::Monitor::addServerPeer( const Connection & server_peer )
128 {
129  m_imp->add( server_peer , false ) ;
130  m_signal.emit( "in" , "start" ) ;
131 }
132 
133 
134 void GNet::Monitor::removeServerPeer( const Connection & server_peer )
135 {
136  m_imp->remove( server_peer , false ) ;
137  m_signal.emit( "in" , "end" ) ;
138 }
139 
140 std::pair<std::string,bool> GNet::Monitor::findCertificate( const std::string & certificate )
141 {
142  return m_imp->findCertificate( certificate ) ;
143 }
144 
145 void GNet::Monitor::report( std::ostream & s , const std::string & px , const std::string & eol ) const
146 {
147  m_imp->report( s , px , eol ) ;
148 }
149 
150 // ==
151 
152 void GNet::MonitorImp::add( const Connection & connection , bool is_client )
153 {
154  bool inserted = m_connections.insert(ConnectionMap::value_type(&connection,ConnectionInfo(is_client))).second ;
155  if( inserted )
156  {
157  if( is_client )
158  m_client_adds++ ;
159  else
160  m_server_peer_adds++ ;
161  }
162 }
163 
164 void GNet::MonitorImp::remove( const Connection & connection , bool is_client )
165 {
166  bool removed = 0U != m_connections.erase( &connection ) ;
167  if( removed )
168  {
169  if( is_client )
170  m_client_removes++ ;
171  else
172  m_server_peer_removes++ ;
173  }
174 }
175 
176 void GNet::MonitorImp::report( std::ostream & s , const std::string & px , const std::string & eol ) const
177 {
178  s << px << "OUT started: " << m_client_adds << eol ;
179  s << px << "OUT finished: " << m_client_removes << eol ;
180  {
181  for( ConnectionMap::const_iterator p = m_connections.begin() ; p != m_connections.end() ; ++p )
182  {
183  if( (*p).second.is_client )
184  {
185  s << px
186  << "OUT: "
187  << (*p).first->localAddress().second.displayString() << " -> "
188  << (*p).first->peerAddress().second.displayString() << eol ;
189  }
190  }
191  }
192 
193  s << px << "IN started: " << m_server_peer_adds << eol ;
194  s << px << "IN finished: " << m_server_peer_removes << eol ;
195  {
196  for( ConnectionMap::const_iterator p = m_connections.begin() ; p != m_connections.end() ; ++p )
197  {
198  if( !(*p).second.is_client )
199  {
200  s << px
201  << "IN: "
202  << (*p).first->localAddress().second.displayString() << " <- "
203  << (*p).first->peerAddress().second.displayString() << eol ;
204  }
205  }
206  }
207 }
208 
209 std::pair<std::string,bool> GNet::MonitorImp::findCertificate( const std::string & certificate )
210 {
211  std::pair<std::string,bool> result( std::string() , false ) ;
212  if( certificate.empty() )
213  return result ;
214 
215  // lru cache
216  Certificates::iterator p = std::find_if( m_certificates.begin() , m_certificates.end() , CertificateMatch(certificate) ) ;
217  if( p != m_certificates.end() )
218  {
219  CertificateInfo tmp = *p ;
220  result.first = G::Str::fromInt( (*p).id ) ;
221  result.second = false ;
222  p = std::remove_if( m_certificates.begin() , m_certificates.end() , CertificateMatch(certificate) ) ;
223  G_ASSERT( p != m_certificates.end() ) ;
224  *p = tmp ;
225  }
226  else
227  {
228  const size_t limit = G::limits::net_certificate_cache_size ;
229  if( m_certificates.size() == limit && !m_certificates.empty() )
230  m_certificates.pop_front() ;
231  int id = ++m_id_generator ;
232  m_certificates.push_back( CertificateInfo(certificate,id) ) ;
233  result.first = G::Str::fromInt( id ) ;
234  result.second = true ;
235  }
236  return result ;
237 }
238 
void removeServerPeer(const Connection &server_peer)
Removes a server connection.
Definition: gmonitor.cpp:134
void report(std::ostream &stream, const std::string &line_prefix=std::string(), const std::string &eol=std::string("\n")) const
Reports itself onto a stream.
Definition: gmonitor.cpp:145
std::pair< std::string, bool > findCertificate(const std::string &certificate)
Definition: gmonitor.cpp:209
G::Signal2< std::string, std::string > & signal()
Provides a callback signal which can be connect()ed to a slot.
Definition: gmonitor.cpp:110
void addClient(const Connection &simple_client)
Adds a client connection.
Definition: gmonitor.cpp:115
void remove(const Connection &, bool is_client)
Definition: gmonitor.cpp:164
static std::string fromInt(int i)
Converts int 'i' to a string.
Definition: gstr.cpp:236
void report(std::ostream &s, const std::string &px, const std::string &eol) const
Definition: gmonitor.cpp:176
A pimple pattern implementation class for GNet::Monitor.
Definition: gmonitor.cpp:35
#define G_ASSERT(test)
Definition: gassert.h:30
std::string certificateId(const std::string &certificiate)
A singleton for monitoring SimpleClient and ServerPeer connections.
Definition: gmonitor.h:43
static Monitor * instance()
Returns the singleton pointer. Returns null if none.
Definition: gmonitor.cpp:105
virtual ~Monitor()
Destructor.
Definition: gmonitor.cpp:99
void removeClient(const Connection &simple_client)
Removes a client connection.
Definition: gmonitor.cpp:121
void addServerPeer(const Connection &server_peer)
Adds a server connection.
Definition: gmonitor.cpp:127
An interface which provides address information for a network connection.
Definition: gconnection.h:39
std::pair< std::string, bool > findCertificate(const std::string &certificate)
Returns a short id for the given certificate and a boolean flag to indicate if it is a new certificat...
Definition: gmonitor.cpp:140
MonitorImp(Monitor &monitor)
Definition: gmonitor.cpp:75
void add(const Connection &, bool is_client)
Definition: gmonitor.cpp:152
Monitor()
Default constructor.
Definition: gmonitor.cpp:92