gloox  0.9.9.12
socks5bytestreamserver.cpp
1 /*
2  Copyright (c) 2007-2008 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 #include "socks5bytestreamserver.h"
15 #include "connectiontcpserver.h"
16 #include "mutexguard.h"
17 
18 namespace gloox
19 {
20 
22  const std::string& ip )
23  : m_tcpServer( 0 ), m_logInstance( logInstance ), m_ip( ip ), m_port( port )
24  {
25  m_tcpServer = new ConnectionTCPServer( this, m_logInstance, m_ip, m_port );
26  }
27 
29  {
30  if( m_tcpServer )
31  delete m_tcpServer;
32 
33  ConnectionMap::const_iterator it = m_connections.begin();
34  for( ; it != m_connections.end(); ++it )
35  delete (*it).first;
36  }
37 
39  {
40  if( m_tcpServer )
41  return m_tcpServer->connect();
42 
43  return ConnNotConnected;
44  }
45 
47  {
48  if( !m_tcpServer )
49  return ConnNotConnected;
50 
51  ConnectionError ce = m_tcpServer->recv( timeout );
52  if( ce != ConnNoError )
53  return ce;
54 
55  ConnectionMap::const_iterator it = m_connections.begin();
56  ConnectionMap::const_iterator it2;
57  while( it != m_connections.end() )
58  {
59  it2 = it++;
60  (*it2).first->recv( timeout );
61  }
62 
63  ConnectionList::iterator it3 = m_oldConnections.begin();
64  ConnectionList::iterator it4;
65  while( it3 != m_oldConnections.end() )
66  {
67  it4 = it3++;
68  delete (*it4);
69  m_oldConnections.erase( it4 );
70  }
71 
72  return ConnNoError;
73  }
74 
76  {
77  if( m_tcpServer )
78  {
79  m_tcpServer->disconnect();
80  m_tcpServer->cleanup();
81  }
82  }
83 
84  ConnectionBase* SOCKS5BytestreamServer::getConnection( const std::string& hash )
85  {
86  MutexGuard mg( m_mutex );
87 
88  ConnectionMap::iterator it = m_connections.begin();
89  for( ; it != m_connections.end(); ++it )
90  {
91  if( (*it).second.hash == hash )
92  {
93  ConnectionBase* conn = (*it).first;
95  m_connections.erase( it );
96  return conn;
97  }
98  }
99 
100  return 0;
101  }
102 
103  void SOCKS5BytestreamServer::registerHash( const std::string& hash )
104  {
105  MutexGuard mg( m_mutex );
106  m_hashes.push_back( hash );
107  }
108 
109  void SOCKS5BytestreamServer::removeHash( const std::string& hash )
110  {
111  MutexGuard mg( m_mutex );
112  m_hashes.remove( hash );
113  }
114 
116  {
117  connection->registerConnectionDataHandler( this );
118  ConnectionInfo ci;
119  ci.state = StateUnnegotiated;
120  m_connections[connection] = ci;
121  }
122 
124  const std::string& data )
125  {
126  ConnectionMap::iterator it = m_connections.find( const_cast<ConnectionBase*>( connection ) );
127  if( it == m_connections.end() )
128  return;
129 
130  switch( (*it).second.state )
131  {
132  case StateDisconnected:
133  (*it).first->disconnect();
134  break;
135  case StateUnnegotiated:
136  {
137  char c[2];
138  c[0] = 0x05;
139  c[1] = (char)0xFF;
140  (*it).second.state = StateDisconnected;
141 
142  if( data.length() >= 3 && data[0] == 0x05 )
143  {
144  unsigned int sz = ( data.length() - 2 < (unsigned int)data[1] )
145  ? ( data.length() - 2 )
146  : ( (unsigned int)data[1] );
147  for( unsigned int i = 2; i < sz + 2; ++i )
148  {
149  if( data[i] == 0x00 )
150  {
151  c[1] = 0x00;
152  (*it).second.state = StateAuthAccepted;
153  break;
154  }
155  }
156  }
157  (*it).first->send( std::string( c, 2 ) );
158  break;
159  }
160  case StateAuthmethodAccepted:
161  // place to implement any future auth support
162  break;
163  case StateAuthAccepted:
164  {
165  std::string reply = data;
166  if( reply.length() < 2 )
167  reply.resize( 2 );
168 
169  reply[0] = 0x05;
170  reply[1] = 0x01; // general SOCKS server failure
171  (*it).second.state = StateDisconnected;
172 
173  if( data.length() == 47 && data[0] == 0x05 && data[1] == 0x01 && data[2] == 0x00
174  && data[3] == 0x03 && data[4] == 0x28 && data[45] == 0x00 && data[46] == 0x00 )
175  {
176  const std::string hash = data.substr( 5, 40 );
177 
178  HashMap::const_iterator ith = m_hashes.begin();
179  for( ; ith != m_hashes.end() && (*ith) != hash; ++ith )
180  ;
181 
182  if( ith != m_hashes.end() )
183  {
184  reply[1] = 0x00;
185  (*it).second.hash = hash;
186  (*it).second.state = StateDestinationAccepted;
187  }
188  }
189  (*it).first->send( reply );
190  break;
191  }
192  case StateDestinationAccepted:
193  case StateActive:
194  // should not happen
195  break;
196  }
197  }
198 
200  {
201  // should never happen, TCP connection is already established
202  }
203 
205  ConnectionError /*reason*/ )
206  {
207  m_connections.erase( const_cast<ConnectionBase*>( connection ) );
208  m_oldConnections.push_back( connection );
209  }
210 
211 }