gloox 1.0
socks5bytestream.cpp
00001 /*
00002   Copyright (c) 2006-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 "socks5bytestream.h"
00015 #include "bytestreamdatahandler.h"
00016 #include "clientbase.h"
00017 #include "connectionbase.h"
00018 #include "connectionsocks5proxy.h"
00019 #include "sha.h"
00020 #include "logsink.h"
00021 
00022 namespace gloox
00023 {
00024 
00025   SOCKS5Bytestream::SOCKS5Bytestream( SOCKS5BytestreamManager* manager, ConnectionBase* connection,
00026                                       LogSink& logInstance, const JID& initiator, const JID& target,
00027                                       const std::string& sid )
00028     : Bytestream( Bytestream::S5B, logInstance, initiator, target, sid ),
00029       m_manager( manager ), m_connection( 0 ), m_socks5( 0 ), m_connected( false )
00030   {
00031     if( connection && connection->state() == StateConnected )
00032       m_open = true;
00033 
00034     setConnectionImpl( connection );
00035   }
00036 
00037   SOCKS5Bytestream::~SOCKS5Bytestream()
00038   {
00039     if( m_open )
00040       close();
00041 
00042     if( m_socks5 )
00043       delete m_socks5;
00044   }
00045 
00046   void SOCKS5Bytestream::setConnectionImpl( ConnectionBase* connection )
00047   {
00048     if( m_socks5 )
00049       delete m_socks5; // deletes m_connection as well
00050 
00051     m_connection = connection;
00052 
00053     SHA sha;
00054     sha.feed( m_sid );
00055     sha.feed( m_initiator.full() );
00056     sha.feed( m_target.full() );
00057     m_socks5 = new ConnectionSOCKS5Proxy( this, connection, m_logInstance, sha.hex(), 0 );
00058   }
00059 
00060   bool SOCKS5Bytestream::connect()
00061   {
00062     if( !m_connection || !m_socks5 || !m_manager )
00063       return false;
00064 
00065     if( m_open )
00066       return true;
00067 
00068     StreamHostList::const_iterator it = m_hosts.begin();
00069     for( ; it != m_hosts.end(); ++it )
00070     {
00071       if( ++it == m_hosts.end() )
00072         m_connected = true;
00073       --it; // FIXME ++it followed by --it is kinda ugly
00074       m_connection->setServer( (*it).host, (*it).port );
00075       if( m_socks5->connect() == ConnNoError )
00076       {
00077         m_proxy = (*it).jid;
00078         m_connected = true;
00079         return true;
00080       }
00081     }
00082 
00083     m_manager->acknowledgeStreamHost( false, JID(), EmptyString );
00084     return false;
00085   }
00086 
00087   bool SOCKS5Bytestream::send( const std::string& data )
00088   {
00089     if( !m_open || !m_connection || !m_socks5 || !m_manager )
00090       return false;
00091 
00092     return m_socks5->send( data );
00093   }
00094 
00095   ConnectionError SOCKS5Bytestream::recv( int timeout )
00096   {
00097     if( !m_connection || !m_socks5 || !m_manager )
00098       return ConnNotConnected;
00099 
00100     return m_socks5->recv( timeout );
00101   }
00102 
00103   void SOCKS5Bytestream::activate()
00104   {
00105     m_open = true;
00106     if( m_handler )
00107       m_handler->handleBytestreamOpen( this );
00108   }
00109 
00110   void SOCKS5Bytestream::close()
00111   {
00112     if( m_open && m_handler )
00113     {
00114       m_open = false;
00115       m_connected = false;
00116       m_socks5->disconnect();
00117       m_handler->handleBytestreamClose( this );
00118     }
00119   }
00120 
00121   void SOCKS5Bytestream::handleReceivedData( const ConnectionBase* /*connection*/, const std::string& data )
00122   {
00123     if( !m_handler )
00124       return;
00125 
00126     if( !m_open )
00127     {
00128       m_open = true;
00129       m_handler->handleBytestreamOpen( this );
00130     }
00131 
00132 //     if( !m_open && data.length() == 2 && data[0] == 0x05 && data[1] == 0x00 )
00133 //     {
00134 //       printf( "received acknowleding zero byte, stream is now open\n" );
00135 //       m_open = true;
00136 //       m_handler->handleBytestream5Open( this );
00137 //       return;
00138 //     }
00139 
00140     if( m_open )
00141       m_handler->handleBytestreamData( this, data );
00142   }
00143 
00144   void SOCKS5Bytestream::handleConnect( const ConnectionBase* /*connection*/ )
00145   {
00146     m_manager->acknowledgeStreamHost( true, m_proxy, m_sid );
00147   }
00148 
00149   void SOCKS5Bytestream::handleDisconnect( const ConnectionBase* /*connection*/, ConnectionError /*reason*/ )
00150   {
00151     if( m_handler && m_connected )
00152       m_handler->handleBytestreamClose( this );
00153   }
00154 
00155 }