socks5bytestreamserver.cpp

00001 /*
00002   Copyright (c) 2007-2008 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 "socks5bytestreamserver.h"
00015 #include "connectiontcpserver.h"
00016 #include "mutexguard.h"
00017 
00018 namespace gloox
00019 {
00020 
00021   SOCKS5BytestreamServer::SOCKS5BytestreamServer( const LogSink& logInstance, int port,
00022                                                   const std::string& ip )
00023     : m_tcpServer( 0 ), m_logInstance( logInstance ), m_ip( ip ), m_port( port )
00024   {
00025     m_tcpServer = new ConnectionTCPServer( this, m_logInstance, m_ip, m_port );
00026   }
00027 
00028   SOCKS5BytestreamServer::~SOCKS5BytestreamServer()
00029   {
00030     if( m_tcpServer )
00031       delete m_tcpServer;
00032 
00033     ConnectionMap::const_iterator it = m_connections.begin();
00034     for( ; it != m_connections.end(); ++it )
00035       delete (*it).first;
00036   }
00037 
00038   ConnectionError SOCKS5BytestreamServer::listen()
00039   {
00040     if( m_tcpServer )
00041       return m_tcpServer->connect();
00042 
00043     return ConnNotConnected;
00044   }
00045 
00046   ConnectionError SOCKS5BytestreamServer::recv( int timeout )
00047   {
00048     if( !m_tcpServer )
00049       return ConnNotConnected;
00050 
00051     ConnectionError ce = m_tcpServer->recv( timeout );
00052     if( ce != ConnNoError )
00053       return ce;
00054 
00055     ConnectionMap::const_iterator it = m_connections.begin();
00056     ConnectionMap::const_iterator it2;
00057     while( it != m_connections.end() )
00058     {
00059       it2 = it++;
00060       (*it2).first->recv( timeout );
00061     }
00062 
00063     ConnectionList::iterator it3 = m_oldConnections.begin();
00064     ConnectionList::iterator it4;
00065     while( it3 != m_oldConnections.end() )
00066     {
00067       it4 = it3++;
00068       delete (*it4);
00069       m_oldConnections.erase( it4 );
00070     }
00071 
00072     return ConnNoError;
00073   }
00074 
00075   void SOCKS5BytestreamServer::stop()
00076   {
00077     if( m_tcpServer )
00078     {
00079       m_tcpServer->disconnect();
00080       m_tcpServer->cleanup();
00081     }
00082   }
00083 
00084   ConnectionBase* SOCKS5BytestreamServer::getConnection( const std::string& hash )
00085   {
00086     MutexGuard mg( m_mutex );
00087 
00088     ConnectionMap::iterator it = m_connections.begin();
00089     for( ; it != m_connections.end(); ++it )
00090     {
00091       if( (*it).second.hash == hash )
00092       {
00093         ConnectionBase* conn = (*it).first;
00094         conn->registerConnectionDataHandler( 0 );
00095         m_connections.erase( it );
00096         return conn;
00097       }
00098     }
00099 
00100     return 0;
00101   }
00102 
00103   void SOCKS5BytestreamServer::registerHash( const std::string& hash )
00104   {
00105     MutexGuard mg( m_mutex );
00106     m_hashes.push_back( hash );
00107   }
00108 
00109   void SOCKS5BytestreamServer::removeHash( const std::string& hash )
00110   {
00111     MutexGuard mg( m_mutex );
00112     m_hashes.remove( hash );
00113   }
00114 
00115   void SOCKS5BytestreamServer::handleIncomingConnection( ConnectionBase* connection )
00116   {
00117     connection->registerConnectionDataHandler( this );
00118     ConnectionInfo ci;
00119     ci.state = StateUnnegotiated;
00120     m_connections[connection] = ci;
00121   }
00122 
00123   void SOCKS5BytestreamServer::handleReceivedData( const ConnectionBase* connection,
00124                                                    const std::string& data )
00125   {
00126     ConnectionMap::iterator it = m_connections.find( const_cast<ConnectionBase*>( connection ) );
00127     if( it == m_connections.end() )
00128       return;
00129 
00130     switch( (*it).second.state )
00131     {
00132       case StateDisconnected:
00133         (*it).first->disconnect();
00134         break;
00135       case StateUnnegotiated:
00136       {
00137         char c[2];
00138         c[0] = 0x05;
00139         c[1] = (char)0xFF;
00140         (*it).second.state = StateDisconnected;
00141 
00142         if( data.length() >= 3 && data[0] == 0x05 )
00143         {
00144           unsigned int sz = ( data.length() - 2 < (unsigned int)data[1] )
00145                               ? ( data.length() - 2 )
00146                               : ( (unsigned int)data[1] );
00147           for( unsigned int i = 2; i < sz + 2; ++i )
00148           {
00149             if( data[i] == 0x00 )
00150             {
00151               c[1] = 0x00;
00152               (*it).second.state = StateAuthAccepted;
00153               break;
00154             }
00155           }
00156         }
00157         (*it).first->send( std::string( c, 2 ) );
00158         break;
00159       }
00160       case StateAuthmethodAccepted:
00161         // place to implement any future auth support
00162         break;
00163       case StateAuthAccepted:
00164       {
00165         std::string reply = data;
00166         if( reply.length() < 2 )
00167           reply.resize( 2 );
00168 
00169         reply[0] = 0x05;
00170         reply[1] = 0x01; // general SOCKS server failure
00171         (*it).second.state = StateDisconnected;
00172 
00173         if( data.length() == 47 && data[0] == 0x05 && data[1] == 0x01 && data[2] == 0x00
00174             && data[3] == 0x03 && data[4] == 0x28 && data[45] == 0x00 && data[46] == 0x00 )
00175         {
00176           const std::string hash = data.substr( 5, 40 );
00177 
00178           HashMap::const_iterator ith = m_hashes.begin();
00179           for( ; ith != m_hashes.end() && (*ith) != hash; ++ith )
00180             ;
00181 
00182           if( ith != m_hashes.end() )
00183           {
00184             reply[1] = 0x00;
00185             (*it).second.hash = hash;
00186             (*it).second.state = StateDestinationAccepted;
00187           }
00188         }
00189         (*it).first->send( reply );
00190         break;
00191       }
00192       case StateDestinationAccepted:
00193       case StateActive:
00194         // should not happen
00195         break;
00196     }
00197   }
00198 
00199   void SOCKS5BytestreamServer::handleConnect( const ConnectionBase* /*connection*/ )
00200   {
00201     // should never happen, TCP connection is already established
00202   }
00203 
00204   void SOCKS5BytestreamServer::handleDisconnect( const ConnectionBase* connection,
00205                                                        ConnectionError /*reason*/ )
00206   {
00207     m_connections.erase( const_cast<ConnectionBase*>( connection ) );
00208     m_oldConnections.push_back( connection );
00209   }
00210 
00211 }

Generated on Mon Dec 7 13:28:19 2009 for gloox by  doxygen 1.6.1