gloox 1.0.27
socks5bytestreamserver.cpp
1/*
2 Copyright (c) 2007-2023 by Jakob Schröter <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 "mutexguard.h"
16#include "util.h"
17
18namespace 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 m_tcpServer = 0;
33
34 m_mutex.lock();
35 ConnectionMap::const_iterator it = m_connections.begin();
36 for( ; it != m_connections.end(); ++it )
37 delete (*it).first;
38 m_connections.clear();
39 util::clearList( m_oldConnections );
40 m_mutex.unlock();
41 }
42
44 {
45 if( m_tcpServer )
46 return m_tcpServer->connect();
47
48 return ConnNotConnected;
49 }
50
52 {
53 if( !m_tcpServer )
54 return ConnNotConnected;
55
56 ConnectionError ce = m_tcpServer->recv( timeout );
57 if( ce != ConnNoError )
58 return ce;
59
60 // First take a snapshot of our connections, and then iterate the snapshot
61 // (so that the live map can be modified by an erase while we
62 // iterate the snapshot of the map)
63 ConnectionMap connectionsSnapshot;
64
65 m_mutex.lock();
66 connectionsSnapshot.insert( m_connections.begin(), m_connections.end() );
67 m_mutex.unlock();
68
69 ConnectionMap::const_iterator it = connectionsSnapshot.begin();
70 for( ; it != connectionsSnapshot.end(); ++it )
71 {
72 (*it).first->recv( timeout );
73 }
74 connectionsSnapshot.clear();
75
76 m_mutex.lock();
77 util::clearList( m_oldConnections );
78 m_mutex.unlock();
79
80 return ConnNoError;
81 }
82
84 {
85 if( m_tcpServer )
86 {
87 m_tcpServer->disconnect();
88 m_tcpServer->cleanup();
89 }
90 }
91
93 {
94 if( m_tcpServer )
95 return m_tcpServer->localPort();
96
97 return m_port;
98 }
99
101 {
102 if( m_tcpServer )
103 return m_tcpServer->localInterface();
104
105 return m_ip;
106 }
107
108 ConnectionBase* SOCKS5BytestreamServer::getConnection( const std::string& hash )
109 {
110 util::MutexGuard mg( m_mutex );
111
112 ConnectionMap::iterator it = m_connections.begin();
113 for( ; it != m_connections.end(); ++it )
114 {
115 if( (*it).second.hash == hash )
116 {
117 ConnectionBase* conn = (*it).first;
119 m_connections.erase( it );
120 return conn;
121 }
122 }
123
124 return 0;
125 }
126
127 void SOCKS5BytestreamServer::registerHash( const std::string& hash )
128 {
129 util::MutexGuard mg( m_mutex );
130 m_hashes.push_back( hash );
131 }
132
133 void SOCKS5BytestreamServer::removeHash( const std::string& hash )
134 {
135 util::MutexGuard mg( m_mutex );
136 m_hashes.remove( hash );
137 }
138
140 {
141 connection->registerConnectionDataHandler( this );
142 ConnectionInfo ci;
143 ci.state = StateUnnegotiated;
144
145 m_mutex.lock();
146 m_connections[connection] = ci;
147 m_mutex.unlock();
148 }
149
151 const std::string& data )
152 {
153 m_mutex.lock();
154 ConnectionMap::iterator it = m_connections.find( const_cast<ConnectionBase*>( connection ) );
155 if( it == m_connections.end() )
156 {
157 m_mutex.unlock();
158 return;
159 }
160 m_mutex.unlock();
161
162 switch( (*it).second.state )
163 {
164 case StateDisconnected:
165 (*it).first->disconnect();
166 break;
167 case StateUnnegotiated:
168 {
169 char c[2];
170 c[0] = 0x05;
171 c[1] = static_cast<char>( 0xFF );
172 (*it).second.state = StateDisconnected;
173
174 if( data.length() >= 3 && data[0] == 0x05 )
175 {
176 unsigned int sz = ( data.length() - 2 < static_cast<unsigned int>( data[1] ) )
177 ? static_cast<unsigned int>( data.length() - 2 )
178 : static_cast<unsigned int>( data[1] );
179 for( unsigned int i = 2; i < sz + 2; ++i )
180 {
181 if( data[i] == 0x00 )
182 {
183 c[1] = 0x00;
184 (*it).second.state = StateAuthAccepted;
185 break;
186 }
187 }
188 }
189 (*it).first->send( std::string( c, 2 ) );
190 break;
191 }
192 case StateAuthmethodAccepted:
193 // place to implement any future auth support
194 break;
195 case StateAuthAccepted:
196 {
197 std::string reply = data;
198 if( reply.length() < 2 )
199 reply.resize( 2 );
200
201 reply[0] = 0x05;
202 reply[1] = 0x01; // general SOCKS server failure
203 (*it).second.state = StateDisconnected;
204
205 if( data.length() == 47 && data[0] == 0x05 && data[1] == 0x01 && data[2] == 0x00
206 && data[3] == 0x03 && data[4] == 0x28 && data[45] == 0x00 && data[46] == 0x00 )
207 {
208 const std::string hash = data.substr( 5, 40 );
209
210 m_mutex.lock();
211 HashMap::const_iterator ith = m_hashes.begin();
212 for( ; ith != m_hashes.end() && (*ith) != hash; ++ith )
213 ;
214
215 if( ith != m_hashes.end() )
216 {
217 reply[1] = 0x00;
218 (*it).second.hash = hash;
219 (*it).second.state = StateDestinationAccepted;
220 }
221 m_mutex.unlock();
222 }
223 (*it).first->send( reply );
224 break;
225 }
226 case StateDestinationAccepted:
227 case StateActive:
228 // should not happen
229 break;
230 }
231 }
232
234 {
235 // should never happen, TCP connection is already established
236 }
237
239 ConnectionError /*reason*/ )
240 {
241 util::MutexGuard mg( m_mutex );
242 m_connections.erase( const_cast<ConnectionBase*>( connection ) );
243 m_oldConnections.push_back( connection );
244 }
245
246}
An abstract base class for a connection.
void registerConnectionDataHandler(ConnectionDataHandler *cdh)
virtual const std::string localInterface() const
virtual int localPort() const
This is an implementation of a simple listening TCP connection.
virtual ConnectionError recv(int timeout=-1)
virtual ConnectionError connect()
An implementation of log sink and source.
Definition: logsink.h:39
const std::string localInterface() const
virtual void handleIncomingConnection(ConnectionBase *server, ConnectionBase *connection)
virtual void handleDisconnect(const ConnectionBase *connection, ConnectionError reason)
virtual void handleConnect(const ConnectionBase *connection)
virtual void handleReceivedData(const ConnectionBase *connection, const std::string &data)
ConnectionError recv(int timeout)
SOCKS5BytestreamServer(const LogSink &logInstance, int port, const std::string &ip=EmptyString)
A simple implementation of a mutex guard.
Definition: mutexguard.h:32
void clearList(std::list< T * > &L)
Definition: util.h:152
The namespace for the gloox library.
Definition: adhoc.cpp:28
ConnectionError
Definition: gloox.h:684
@ ConnNotConnected
Definition: gloox.h:715
@ ConnNoError
Definition: gloox.h:685