Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

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

Generated on Mon Sep 1 09:25:11 2008 for gloox by  doxygen 1.4.1