gloox 1.0

connectiontls.cpp

00001 /*
00002  * Copyright (c) 2007-2009 by Jakob Schroeter <js@camaya.net>
00003  * This file is part of the gloox library. http://camaya.net/gloox
00004  *
00005  * This software is distributed under a license. The full license
00006  * agreement can be found in the file LICENSE in this distribution.
00007  * This software may not be copied, modified, sold or distributed
00008  * other than expressed in the named license agreement.
00009  *
00010  * This software is distributed without any warranty.
00011  */
00012 
00013 
00014 #include "connectiontls.h"
00015 #include "tlsdefault.h"
00016 
00017 namespace gloox
00018 {
00019 
00020   ConnectionTLS::ConnectionTLS( ConnectionDataHandler* cdh, ConnectionBase* conn, const LogSink& log )
00021     : ConnectionBase( cdh ),
00022       m_connection( conn ), m_tls( 0 ), m_tlsHandler( 0 ),
00023       m_log( log )
00024   {
00025     if( m_connection )
00026       m_connection->registerConnectionDataHandler( this );
00027   }
00028 
00029   ConnectionTLS::ConnectionTLS( ConnectionBase* conn, const LogSink& log )
00030     : ConnectionBase( 0 ),
00031       m_connection( conn ), m_tls( 0 ), m_tlsHandler( 0 ), m_log( log )
00032   {
00033     if( m_connection )
00034       m_connection->registerConnectionDataHandler( this );
00035   }
00036 
00037   ConnectionTLS::~ConnectionTLS()
00038   {
00039     delete m_connection;
00040     delete m_tls;
00041   }
00042 
00043   void ConnectionTLS::setConnectionImpl( ConnectionBase* connection )
00044   {
00045     if( m_connection )
00046       m_connection->registerConnectionDataHandler( 0 );
00047 
00048     m_connection = connection;
00049 
00050     if( m_connection )
00051       m_connection->registerConnectionDataHandler( this );
00052   }
00053 
00054   ConnectionError ConnectionTLS::connect()
00055   {
00056     if( !m_connection )
00057       return ConnNotConnected;
00058 
00059     if( m_state == StateConnected )
00060       return ConnNoError;
00061 
00062     if( !m_tls )
00063       m_tls = getTLSBase( this, m_connection->server() );
00064 
00065     if( !m_tls )
00066       return ConnTlsNotAvailable;
00067 
00068     if( !m_tls->init( m_clientKey, m_clientCerts, m_cacerts ) )
00069       return ConnTlsFailed;
00070 
00071 //     m_tls->setCACerts( m_cacerts );
00072 //     m_tls->setClientCert( m_clientKey, m_clientCerts );
00073 
00074     m_state = StateConnecting;
00075 
00076     if( m_connection->state() != StateConnected )
00077       return m_connection->connect();
00078 
00079     if( m_tls->handshake() )
00080       return ConnNoError;
00081     else
00082       return ConnTlsFailed;
00083  }
00084 
00085   ConnectionError ConnectionTLS::recv( int timeout )
00086   {
00087     if( m_connection->state() == StateConnected )
00088     {
00089       return m_connection->recv( timeout );
00090     }
00091     else
00092     {
00093       m_log.log( LogLevelWarning, LogAreaClassConnectionTLS,
00094                  "Attempt to receive data on a connection that is not connected (or is connecting)" );
00095       return ConnNotConnected;
00096     }
00097   }
00098 
00099   bool ConnectionTLS::send( const std::string& data )
00100   {
00101     if( m_state != StateConnected )
00102       return false;
00103 
00104     m_tls->encrypt( data );
00105     return true;
00106   }
00107 
00108   ConnectionError ConnectionTLS::receive()
00109   {
00110     if( m_connection )
00111       return m_connection->receive();
00112     else
00113       return ConnNotConnected;
00114   }
00115 
00116   void ConnectionTLS::disconnect()
00117   {
00118     if( m_connection )
00119       m_connection->disconnect();
00120 
00121     cleanup();
00122   }
00123 
00124   void ConnectionTLS::cleanup()
00125   {
00126     if( m_connection )
00127       m_connection->cleanup();
00128     if( m_tls )
00129       m_tls->cleanup();
00130 
00131     m_state = StateDisconnected;
00132   }
00133 
00134   void ConnectionTLS::getStatistics( long int& totalIn, long int& totalOut )
00135   {
00136     if( m_connection )
00137       m_connection->getStatistics( totalIn, totalOut );
00138   }
00139 
00140   ConnectionBase* ConnectionTLS::newInstance() const
00141   {
00142     ConnectionBase* newConn = 0;
00143     if( m_connection )
00144       newConn = m_connection->newInstance();
00145     return new ConnectionTLS( m_handler, newConn, m_log );
00146   }
00147 
00148   void ConnectionTLS::handleReceivedData( const ConnectionBase* /*connection*/, const std::string& data )
00149   {
00150     if( m_tls )
00151       m_tls->decrypt( data );
00152   }
00153 
00154   void ConnectionTLS::handleConnect( const ConnectionBase* /*connection*/ )
00155   {
00156     if( m_tls )
00157       m_tls->handshake();
00158   }
00159 
00160   void ConnectionTLS::handleDisconnect( const ConnectionBase* /*connection*/, ConnectionError reason )
00161   {
00162     if( m_handler )
00163       m_handler->handleDisconnect( this, reason );
00164 
00165     cleanup();
00166   }
00167 
00168   void ConnectionTLS::handleEncryptedData( const TLSBase* /*tls*/, const std::string& data )
00169   {
00170     if( m_connection )
00171       m_connection->send( data );
00172   }
00173 
00174   void ConnectionTLS::handleDecryptedData( const TLSBase* /*tls*/, const std::string& data )
00175   {
00176     if( m_handler )
00177       m_handler->handleReceivedData( this, data );
00178     else
00179     {
00180       m_log.log( LogLevelDebug, LogAreaClassConnectionTLS, "Data received and decrypted but no handler" );
00181     }
00182   }
00183 
00184   void ConnectionTLS::handleHandshakeResult( const TLSBase* tls, bool success, CertInfo& certinfo )
00185   {
00186     if( success )
00187     {
00188       m_state = StateConnected;
00189       m_log.log( LogLevelDebug, LogAreaClassConnectionTLS, "TLS handshake succeeded" );
00190       if( m_tlsHandler )
00191         m_tlsHandler->handleHandshakeResult( tls, success, certinfo );
00192       if( m_handler )
00193         m_handler->handleConnect( this );
00194     }
00195     else
00196     {
00197       m_state = StateDisconnected;
00198       m_log.log( LogLevelWarning, LogAreaClassConnectionTLS, "TLS handshake failed" );
00199       if( m_tlsHandler )
00200         m_tlsHandler->handleHandshakeResult( tls, success, certinfo );
00201     }
00202   }
00203 
00204 }