E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gmonitor.cpp
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 // gmonitor.cpp
19 //
20
21 #include "gdef.h"
22 #include "glimits.h"
23 #include "gmonitor.h"
24 #include "gstr.h"
25 #include "gstrings.h"
26 #include "gassert.h"
27 #include <map>
28 #include <deque>
29 #include <algorithm> // std::swap
30 #include <utility> // std::swap
31
32 /// \class GNet::MonitorImp
33 /// A pimple-pattern implementation class for GNet::Monitor.
34 ///
35 class GNet::MonitorImp
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 void report( G::StringArray & ) const ;
43 std::string certificateId( const std::string & certificiate ) ;
44 std::pair<std::string,bool> findCertificate( const std::string & certificate ) ;
45
46 private:
47 static std::string join( const std::string & , const std::string & ) ;
48 static void add( G::StringArray & , const std::string & , unsigned int , const std::string & ,
49 unsigned int , const std::string & ) ;
50 static void add( G::StringArray & , const std::string & , const std::string & , const std::string & ,
51 const std::string & , const std::string & ) ;
52
53 private:
54 struct ConnectionInfo
55 {
56 bool is_client ;
57 explicit ConnectionInfo( bool is_client_ ) : is_client(is_client_) {}
58 } ;
59 struct CertificateInfo
60 {
61 std::string certificate ;
62 int id ;
63 CertificateInfo( const std::string & c , int id_ ) : certificate(c) , id(id_) {}
64 bool match( std::string s ) const { return s == certificate ; }
65 } ;
66 struct CertificateMatch
67 {
68 const std::string & m_s ;
69 explicit CertificateMatch( const std::string & s ) : m_s(s) {}
70 bool operator()( const CertificateInfo & o ) const { return o.match(m_s) ; }
71 } ;
72 typedef std::map<const Connection*,ConnectionInfo> ConnectionMap ;
73 typedef std::deque<CertificateInfo> Certificates ;
74 ConnectionMap m_connections ;
75 Certificates m_certificates ;
76 int m_id_generator ;
77 unsigned long m_client_adds ;
78 unsigned long m_client_removes ;
79 unsigned long m_server_peer_adds ;
80 unsigned long m_server_peer_removes ;
81 } ;
82
83 GNet::MonitorImp::MonitorImp( Monitor & ) :
84 m_id_generator(0) ,
85 m_client_adds(0UL) ,
86 m_client_removes(0UL) ,
87 m_server_peer_adds(0UL) ,
88 m_server_peer_removes(0UL)
89 {
90 }
91
92 // ===
93
94 GNet::Monitor * & GNet::Monitor::pthis()
95 {
96 static GNet::Monitor * p = nullptr ;
97 return p ;
98 }
99
100 GNet::Monitor::Monitor() :
101 m_imp( new MonitorImp(*this) )
102 {
103 G_ASSERT( pthis() == nullptr ) ;
104 pthis() = this ;
105 }
106
107 GNet::Monitor::~Monitor()
108 {
109 delete m_imp ;
110 pthis() = nullptr ;
111 }
112
113 GNet::Monitor * GNet::Monitor::instance()
114 {
115 return pthis() ;
116 }
117
118 G::Slot::Signal2<std::string,std::string> & GNet::Monitor::signal()
119 {
120 return m_signal ;
121 }
122
123 void GNet::Monitor::addClient( const Connection & client )
124 {
125 m_imp->add( client , true ) ;
126 m_signal.emit( "out" , "start" ) ;
127 }
128
129 void GNet::Monitor::removeClient( const Connection & client )
130 {
131 m_imp->remove( client , true ) ;
132 m_signal.emit( "out" , "end" ) ;
133 }
134
135 void GNet::Monitor::addServerPeer( const Connection & server_peer )
136 {
137 m_imp->add( server_peer , false ) ;
138 m_signal.emit( "in" , "start" ) ;
139 }
140
141
142 void GNet::Monitor::removeServerPeer( const Connection & server_peer )
143 {
144 m_imp->remove( server_peer , false ) ;
145 m_signal.emit( "in" , "end" ) ;
146 }
147
148 std::pair<std::string,bool> GNet::Monitor::findCertificate( const std::string & certificate )
149 {
150 return m_imp->findCertificate( certificate ) ;
151 }
152
153 void GNet::Monitor::report( std::ostream & s , const std::string & px , const std::string & eol ) const
154 {
155 m_imp->report( s , px , eol ) ;
156 }
157
158 void GNet::Monitor::report( G::StringArray & out ) const
159 {
160 m_imp->report( out ) ;
161 }
162
163 // ==
164
165 void GNet::MonitorImp::add( const Connection & connection , bool is_client )
166 {
167 bool inserted = m_connections.insert(ConnectionMap::value_type(&connection,ConnectionInfo(is_client))).second ;
168 if( inserted )
169 {
170 if( is_client )
171 m_client_adds++ ;
172 else
173 m_server_peer_adds++ ;
174 }
175 }
176
177 void GNet::MonitorImp::remove( const Connection & connection , bool is_client )
178 {
179 bool removed = 0U != m_connections.erase( &connection ) ;
180 if( removed )
181 {
182 if( is_client )
183 m_client_removes++ ;
184 else
185 m_server_peer_removes++ ;
186 }
187 }
188
189 void GNet::MonitorImp::report( std::ostream & s , const std::string & px , const std::string & eol ) const
190 {
191 s << px << "OUT started: " << m_client_adds << eol ;
192 s << px << "OUT finished: " << m_client_removes << eol ;
193 {
194 for( ConnectionMap::const_iterator p = m_connections.begin() ; p != m_connections.end() ; ++p )
195 {
196 if( (*p).second.is_client )
197 {
198 s << px
199 << "OUT: "
200 << (*p).first->localAddress().second.displayString() << " -> "
201 << (*p).first->connectionState() << eol ;
202 }
203 }
204 }
205
206 s << px << "IN started: " << m_server_peer_adds << eol ;
207 s << px << "IN finished: " << m_server_peer_removes << eol ;
208 {
209 for( ConnectionMap::const_iterator p = m_connections.begin() ; p != m_connections.end() ; ++p )
210 {
211 if( !(*p).second.is_client )
212 {
213 s << px
214 << "IN: "
215 << (*p).first->localAddress().second.displayString() << " <- "
216 << (*p).first->peerAddress().second.displayString() << eol ;
217 }
218 }
219 }
220 }
221
222 void GNet::MonitorImp::report( G::StringArray & out ) const
223 {
224 add( out , "Outgoing connections" , m_client_adds , "started" , m_client_removes , "finished" ) ;
225 add( out , "Incoming connections" , m_server_peer_adds , "started" , m_server_peer_removes , "finished" ) ;
226 for( ConnectionMap::const_iterator p = m_connections.begin() ; p != m_connections.end() ; ++p )
227 {
228 if( (*p).second.is_client )
229 {
230 add( out , "Outgoing connection" , (*p).first->localAddress().second.displayString() , "-->" ,
231 (*p).first->connectionState() , "" ) ;
232 }
233 }
234 for( ConnectionMap::const_iterator p = m_connections.begin() ; p != m_connections.end() ; ++p )
235 {
236 if( !(*p).second.is_client )
237 add( out , "Incoming connection" , (*p).first->localAddress().second.displayString() , "<--" ,
238 (*p).first->peerAddress().second.displayString() , "" ) ;
239 }
240 }
241
242 void GNet::MonitorImp::add( G::StringArray & out , const std::string & key ,
243 unsigned int value_1 , const std::string & suffix_1 ,
244 unsigned int value_2 , const std::string & suffix_2 )
245 {
246 add( out , key , G::Str::fromUInt(value_1) , suffix_1 , G::Str::fromUInt(value_2) , suffix_2 ) ;
247 }
248
249 std::string GNet::MonitorImp::join( const std::string & s1 , const std::string & s2 )
250 {
251 return s2.empty() ? s1 : ( s1 + " " + s2 ) ;
252 }
253
254 void GNet::MonitorImp::add( G::StringArray & out , const std::string & key ,
255 const std::string & value_1 , const std::string & suffix_1 ,
256 const std::string & value_2 , const std::string & suffix_2 )
257 {
258 out.push_back( key ) ;
259 out.push_back( join(value_1,suffix_1) ) ;
260 out.push_back( join(value_2,suffix_2) ) ;
261 }
262
263 std::pair<std::string,bool> GNet::MonitorImp::findCertificate( const std::string & certificate )
264 {
265 std::pair<std::string,bool> result( std::string() , false ) ;
266 if( certificate.empty() )
267 return result ;
268
269 // lru cache
270 Certificates::iterator const end = m_certificates.end() ;
271 Certificates::iterator p = std::find_if( m_certificates.begin() , end , CertificateMatch(certificate) ) ;
272 if( p != end )
273 {
274 CertificateInfo tmp = *p ;
275 result.first = G::Str::fromInt( (*p).id ) ;
276 result.second = false ;
277 p = std::remove_if( m_certificates.begin() , end , CertificateMatch(certificate) ) ;
278 G_ASSERT( p != end ) ;
279 *p = tmp ; // (remove_if() doesnt remove; it moves the item to the end and returns its iterator)
280 }
281 else
282 {
283 const size_t limit = G::limits::net_certificate_cache_size ;
284 if( m_certificates.size() == limit && !m_certificates.empty() )
285 m_certificates.pop_front() ;
286 int id = ++m_id_generator ;
287 m_certificates.push_back( CertificateInfo(certificate,id) ) ;
288 result.first = G::Str::fromInt( id ) ;
289 result.second = true ;
290 }
291 return result ;
292 }
293
GNet::Monitor::removeServerPeer
void removeServerPeer(const Connection &server_peer)
Removes a server connection.
Definition: gmonitor.cpp:142
gstrings.h
G::Slot::Signal2< std::string, std::string >
GNet::Monitor::report
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:153
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
GNet::Monitor::addClient
void addClient(const Connection &simple_client)
Adds a client connection.
Definition: gmonitor.cpp:123
G::Str::fromInt
static std::string fromInt(int i)
Converts int 'i' to a string.
Definition: gstr.cpp:332
GNet::Monitor::signal
G::Slot::Signal2< std::string, std::string > & signal()
Provides a callback signal which can be connect()ed to a slot.
Definition: gmonitor.cpp:118
glimits.h
GNet::MonitorImp
A pimple-pattern implementation class for GNet::Monitor.
Definition: gmonitor.cpp:35
G::Str::fromUInt
static std::string fromUInt(unsigned int ui)
Converts unsigned int 'ui' to a string.
Definition: gstr.cpp:353
gstr.h
gassert.h
GNet::Monitor
A singleton for monitoring GNet::SimpleClient and GNet::ServerPeer connections and for storing their ...
Definition: gmonitor.h:41
GNet::Monitor::instance
static Monitor * instance()
Returns the singleton pointer. Returns null if none.
Definition: gmonitor.cpp:113
GNet::Monitor::~Monitor
virtual ~Monitor()
Destructor.
Definition: gmonitor.cpp:107
GNet::Monitor::removeClient
void removeClient(const Connection &simple_client)
Removes a client connection.
Definition: gmonitor.cpp:129
gmonitor.h
GNet::Monitor::addServerPeer
void addServerPeer(const Connection &server_peer)
Adds a server connection.
Definition: gmonitor.cpp:135
GNet::Connection
An abstract interface which provides address information for a network connection.
Definition: gconnection.h:37
GNet::Monitor::findCertificate
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:148
GNet::Monitor::Monitor
Monitor()
Default constructor.
Definition: gmonitor.cpp:100