gloox 1.0
|
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 "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 return ConnNoError; 00066 } 00067 00068 void SOCKS5BytestreamServer::stop() 00069 { 00070 if( m_tcpServer ) 00071 { 00072 m_tcpServer->disconnect(); 00073 m_tcpServer->cleanup(); 00074 } 00075 } 00076 00077 int SOCKS5BytestreamServer::localPort() const 00078 { 00079 if( m_tcpServer ) 00080 return m_tcpServer->localPort(); 00081 00082 return m_port; 00083 } 00084 00085 const std::string SOCKS5BytestreamServer::localInterface() const 00086 { 00087 if( m_tcpServer ) 00088 return m_tcpServer->localInterface(); 00089 00090 return m_ip; 00091 } 00092 00093 ConnectionBase* SOCKS5BytestreamServer::getConnection( const std::string& hash ) 00094 { 00095 util::MutexGuard mg( m_mutex ); 00096 00097 ConnectionMap::iterator it = m_connections.begin(); 00098 for( ; it != m_connections.end(); ++it ) 00099 { 00100 if( (*it).second.hash == hash ) 00101 { 00102 ConnectionBase* conn = (*it).first; 00103 conn->registerConnectionDataHandler( 0 ); 00104 m_connections.erase( it ); 00105 return conn; 00106 } 00107 } 00108 00109 return 0; 00110 } 00111 00112 void SOCKS5BytestreamServer::registerHash( const std::string& hash ) 00113 { 00114 util::MutexGuard mg( m_mutex ); 00115 m_hashes.push_back( hash ); 00116 } 00117 00118 void SOCKS5BytestreamServer::removeHash( const std::string& hash ) 00119 { 00120 util::MutexGuard mg( m_mutex ); 00121 m_hashes.remove( hash ); 00122 } 00123 00124 void SOCKS5BytestreamServer::handleIncomingConnection( ConnectionBase* /*server*/, ConnectionBase* connection ) 00125 { 00126 connection->registerConnectionDataHandler( this ); 00127 ConnectionInfo ci; 00128 ci.state = StateUnnegotiated; 00129 m_connections[connection] = ci; 00130 } 00131 00132 void SOCKS5BytestreamServer::handleReceivedData( const ConnectionBase* connection, 00133 const std::string& data ) 00134 { 00135 ConnectionMap::iterator it = m_connections.find( const_cast<ConnectionBase*>( connection ) ); 00136 if( it == m_connections.end() ) 00137 return; 00138 00139 switch( (*it).second.state ) 00140 { 00141 case StateDisconnected: 00142 (*it).first->disconnect(); 00143 break; 00144 case StateUnnegotiated: 00145 { 00146 char c[2]; 00147 c[0] = 0x05; 00148 c[1] = (char)(unsigned char)0xFF; 00149 (*it).second.state = StateDisconnected; 00150 00151 if( data.length() >= 3 && data[0] == 0x05 ) 00152 { 00153 unsigned int sz = ( data.length() - 2 < static_cast<unsigned int>( data[1] ) ) 00154 ? static_cast<unsigned int>( data.length() - 2 ) 00155 : static_cast<unsigned int>( data[1] ); 00156 for( unsigned int i = 2; i < sz + 2; ++i ) 00157 { 00158 if( data[i] == 0x00 ) 00159 { 00160 c[1] = 0x00; 00161 (*it).second.state = StateAuthAccepted; 00162 break; 00163 } 00164 } 00165 } 00166 (*it).first->send( std::string( c, 2 ) ); 00167 break; 00168 } 00169 case StateAuthmethodAccepted: 00170 // place to implement any future auth support 00171 break; 00172 case StateAuthAccepted: 00173 { 00174 std::string reply = data; 00175 if( reply.length() < 2 ) 00176 reply.resize( 2 ); 00177 00178 reply[0] = 0x05; 00179 reply[1] = 0x01; // general SOCKS server failure 00180 (*it).second.state = StateDisconnected; 00181 00182 if( data.length() == 47 && data[0] == 0x05 && data[1] == 0x01 && data[2] == 0x00 00183 && data[3] == 0x03 && data[4] == 0x28 && data[45] == 0x00 && data[46] == 0x00 ) 00184 { 00185 const std::string hash = data.substr( 5, 40 ); 00186 00187 HashMap::const_iterator ith = m_hashes.begin(); 00188 for( ; ith != m_hashes.end() && (*ith) != hash; ++ith ) 00189 ; 00190 00191 if( ith != m_hashes.end() ) 00192 { 00193 reply[1] = 0x00; 00194 (*it).second.hash = hash; 00195 (*it).second.state = StateDestinationAccepted; 00196 } 00197 } 00198 (*it).first->send( reply ); 00199 break; 00200 } 00201 case StateDestinationAccepted: 00202 case StateActive: 00203 // should not happen 00204 break; 00205 } 00206 } 00207 00208 void SOCKS5BytestreamServer::handleConnect( const ConnectionBase* /*connection*/ ) 00209 { 00210 // should never happen, TCP connection is already established 00211 } 00212 00213 void SOCKS5BytestreamServer::handleDisconnect( const ConnectionBase* connection, 00214 ConnectionError /*reason*/ ) 00215 { 00216 m_connections.erase( const_cast<ConnectionBase*>( connection ) ); 00217 m_oldConnections.push_back( connection ); 00218 } 00219 00220 }