gloox  1.0.1
connectiontls.cpp
1 /*
2  * Copyright (c) 2007-2012 by Jakob Schroeter <js@camaya.net>
3  * This file is part of the gloox library. http://camaya.net/gloox
4  *
5  * This software is distributed under a license. The full license
6  * agreement can be found in the file LICENSE in this distribution.
7  * This software may not be copied, modified, sold or distributed
8  * other than expressed in the named license agreement.
9  *
10  * This software is distributed without any warranty.
11  */
12 
13 
14 #include "connectiontls.h"
15 #include "tlsdefault.h"
16 
17 #include <cstdio>
18 
19 namespace gloox
20 {
21 
23  : ConnectionBase( cdh ),
24  m_connection( conn ), m_tls( 0 ), m_tlsHandler( 0 ),
25  m_log( log )
26  {
27  if( m_connection )
28  m_connection->registerConnectionDataHandler( this );
29  }
30 
32  : ConnectionBase( 0 ),
33  m_connection( conn ), m_tls( 0 ), m_tlsHandler( 0 ), m_log( log )
34  {
35  if( m_connection )
36  m_connection->registerConnectionDataHandler( this );
37  }
38 
40  {
41  delete m_connection;
42  delete m_tls;
43  }
44 
46  {
47  if( m_connection )
48  m_connection->registerConnectionDataHandler( 0 );
49 
50  m_connection = connection;
51 
52  if( m_connection )
53  m_connection->registerConnectionDataHandler( this );
54  }
55 
57  {
58  if( !m_connection )
59  return ConnNotConnected;
60 
61  if( m_state == StateConnected )
62  return ConnNoError;
63 
64  if( !m_tls )
65  m_tls = getTLSBase( this, m_connection->server() );
66 
67  if( !m_tls )
68  return ConnTlsNotAvailable;
69 
70  if( !m_tls->init( m_clientKey, m_clientCerts, m_cacerts ) )
71  return ConnTlsFailed;
72 
73 // m_tls->setCACerts( m_cacerts );
74 // m_tls->setClientCert( m_clientKey, m_clientCerts );
75 
77 
78  if( m_connection->state() != StateConnected )
79  return m_connection->connect();
80 
81  if( m_tls->handshake() )
82  return ConnNoError;
83  else
84  return ConnTlsFailed;
85  }
86 
88  {
89  if( m_connection->state() == StateConnected )
90  {
91  return m_connection->recv( timeout );
92  }
93  else
94  {
96  "Attempt to receive data on a connection that is not connected (or is connecting)" );
97  return ConnNotConnected;
98  }
99  }
100 
101  bool ConnectionTLS::send( const std::string& data )
102  {
103  if( m_state != StateConnected )
104  return false;
105 
106  m_tls->encrypt( data );
107  return true;
108  }
109 
111  {
112  if( m_connection )
113  return m_connection->receive();
114  else
115  return ConnNotConnected;
116  }
117 
119  {
120  if( m_connection )
121  m_connection->disconnect();
122 
123  cleanup();
124  }
125 
127  {
128  if( m_connection )
129  m_connection->cleanup();
130  if( m_tls )
131  m_tls->cleanup();
132 
134  }
135 
136  void ConnectionTLS::getStatistics( long int& totalIn, long int& totalOut )
137  {
138  if( m_connection )
139  m_connection->getStatistics( totalIn, totalOut );
140  }
141 
143  {
144  ConnectionBase* newConn = 0;
145  if( m_connection )
146  newConn = m_connection->newInstance();
147  return new ConnectionTLS( m_handler, newConn, m_log );
148  }
149 
150  void ConnectionTLS::handleReceivedData( const ConnectionBase* /*connection*/, const std::string& data )
151  {
152  if( m_tls )
153  m_tls->decrypt( data );
154  }
155 
156  void ConnectionTLS::handleConnect( const ConnectionBase* /*connection*/ )
157  {
158  if( m_tls )
159  m_tls->handshake();
160  }
161 
162  void ConnectionTLS::handleDisconnect( const ConnectionBase* /*connection*/, ConnectionError reason )
163  {
164  if( m_handler )
165  m_handler->handleDisconnect( this, reason );
166 
167  cleanup();
168  }
169 
170  void ConnectionTLS::handleEncryptedData( const TLSBase* /*tls*/, const std::string& data )
171  {
172  if( m_connection )
173  m_connection->send( data );
174  }
175 
176  void ConnectionTLS::handleDecryptedData( const TLSBase* /*tls*/, const std::string& data )
177  {
178  if( m_handler )
179  m_handler->handleReceivedData( this, data );
180  else
181  {
182  m_log.log( LogLevelDebug, LogAreaClassConnectionTLS, "Data received and decrypted but no handler" );
183  }
184  }
185 
186  void ConnectionTLS::handleHandshakeResult( const TLSBase* tls, bool success, CertInfo& certinfo )
187  {
188  if( success )
189  {
191  m_log.log( LogLevelDebug, LogAreaClassConnectionTLS, "TLS handshake succeeded" );
192  if( m_tlsHandler )
193  m_tlsHandler->handleHandshakeResult( tls, success, certinfo );
194  if( m_handler )
195  m_handler->handleConnect( this );
196  }
197  else
198  {
200  m_log.log( LogLevelWarning, LogAreaClassConnectionTLS, "TLS handshake failed" );
201  if( m_tlsHandler )
202  m_tlsHandler->handleHandshakeResult( tls, success, certinfo );
203  cleanup();
204  if( m_handler )
206  }
207  }
208 
209 }