Upstream tarball 20080414
[amule.git] / src / Proxy.h
blob38b279bbf8159ca4b8a850ba4996c4ff6a653cb1
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2004-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2004-2008 Marcelo Jimenez ( phoenix@amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #ifndef __PROXY_H__
27 #define __PROXY_H__
29 #include <wx/wx.h>
31 #include "amuleIPV4Address.h" // For amuleIPV4address
32 #include "StateMachine.h" // For CStateMachine
34 /******************************************************************************/
37 * SOCKS4 protocol implementation according to:
38 * - "SOCKS: A protocol for TCP proxy across firewalls":
39 * amule-root/docs/socks4.protocol
41 const unsigned char SOCKS4_VERSION = 0x04;
43 const unsigned char SOCKS4_CMD_CONNECT = 0x01;
44 const unsigned char SOCKS4_CMD_BIND = 0x02;
46 const unsigned char SOCKS4_REPLY_CODE = 0;
47 const unsigned char SOCKS4_REPLY_GRANTED = 90;
48 const unsigned char SOCKS4_REPLY_FAILED = 91;
49 const unsigned char SOCKS4_REPLY_FAILED_NO_IDENTD = 92;
50 const unsigned char SOCKS4_REPLY_FAILED_DIFFERENT_USERIDS = 93;
53 * SOCKS5 protocol implementation according to:
54 * - RFC-1928: SOCKS Protocol Version 5
55 * - RFC-1929: username/password Authentication for SOCKS V5
57 * Also, for the future :) :
58 * - RFC-1961: GSS-API Authentication Method for SOCKS Version 5
59 * - RFC-1508: Generic Security Service Application Program Interface
60 * - RFC-1509: Genecic Security Service API: C-bindings
64 const unsigned char SOCKS5_VERSION = 0x05;
66 const unsigned char SOCKS5_AUTH_METHOD_NO_AUTH_REQUIRED = 0x00;
67 const unsigned char SOCKS5_AUTH_METHOD_GSSAPI = 0x01;
68 const unsigned char SOCKS5_AUTH_METHOD_USERNAME_PASSWORD = 0x02;
69 const unsigned char SOCKS5_AUTH_METHOD_NO_ACCEPTABLE_METHODS = 0xFF;
71 const unsigned char SOCKS5_AUTH_VERSION_USERNAME_PASSWORD = 0x01;
73 const unsigned char SOCKS5_CMD_CONNECT = 0x01;
74 const unsigned char SOCKS5_CMD_BIND = 0x02;
75 const unsigned char SOCKS5_CMD_UDP_ASSOCIATE = 0x03;
77 const unsigned char SOCKS5_RSV = 0x00;
79 const unsigned char SOCKS5_ATYP_IPV4_ADDRESS = 0x01;
80 const unsigned char SOCKS5_ATYP_DOMAINNAME = 0x03;
81 const unsigned char SOCKS5_ATYP_IPV6_ADDRESS = 0x04;
83 const unsigned char SOCKS5_REPLY_SUCCEED = 0x00;
84 const unsigned char SOCKS5_REPLY_GENERAL_SERVER_FAILURE = 0x01;
85 const unsigned char SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02;
86 const unsigned char SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03;
87 const unsigned char SOCKS5_REPLY_HOST_UNREACHABLE = 0x04;
88 const unsigned char SOCKS5_REPLY_CONNECTION_REFUSED = 0x05;
89 const unsigned char SOCKS5_REPLY_TTL_EXPIRED = 0x06;
90 const unsigned char SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07;
91 const unsigned char SOCKS5_REPLY_ATYP_NOT_SUPPORTED = 0x08;
93 //------------------------------------------------------------------------------
94 // CProxyType
95 //------------------------------------------------------------------------------
98 * These constants must match the integer values saved in the configuration file,
99 * DO NOT CHANGE THIS ORDER!!!
101 enum CProxyType {
102 PROXY_NONE = -1,
103 PROXY_SOCKS5,
104 PROXY_SOCKS4,
105 PROXY_HTTP,
106 PROXY_SOCKS4a
110 //------------------------------------------------------------------------------
111 // CProxyData
112 //------------------------------------------------------------------------------
114 * The ProxyData class will hold information about the proxy server to be used.
116 class CProxyData
118 public:
120 * Default constructor.
122 CProxyData();
124 * Constructor.
126 * @param proxyEnable Whether proxy is enabled or not.
127 * @param proxyType The type of the proxy server.
128 * @param proxyHostName The proxy host name or IP address.
129 * @param proxyPort The proxy port number.
130 * @param enablePassword Whether authentication should be performed.
131 * @param userName The user name to authenticate to the server.
132 * @param password The password to authenticate to the server.
134 CProxyData(
135 bool proxyEnable,
136 CProxyType proxyType,
137 const wxString &proxyHostName,
138 unsigned short proxyPort,
139 bool enablePassword,
140 const wxString &userName,
141 const wxString &password
144 * Clears the object contents.
146 void Clear();
148 public:
149 //! Whether proxy is enabled or not.
150 bool m_proxyEnable;
151 //! The type of the proxy server.
152 CProxyType m_proxyType;
153 //! The proxy host name or IP address.
154 wxString m_proxyHostName;
155 //! The proxy port number.
156 unsigned short m_proxyPort;
157 //! Whether authentication should be performed.
158 bool m_enablePassword;
159 //! The user name to authenticate to the server.
160 wxString m_userName;
161 //! The password to authenticate to the server.
162 wxString m_password;
165 //------------------------------------------------------------------------------
166 // CProxyEventHandler
167 //------------------------------------------------------------------------------
169 * Event handler object used during proxy negotiation.
171 class CProxyEventHandler : public wxEvtHandler {
172 public:
174 * Constructor.
176 CProxyEventHandler();
178 private:
180 * Event handler function.
182 void ProxySocketHandler(wxSocketEvent &event);
183 DECLARE_EVENT_TABLE()
186 //------------------------------------------------------------------------------
187 // CProxyStateMachine
188 //------------------------------------------------------------------------------
189 /* This size is just to be a little bit greater than the UDP buffer used in aMule.
190 * Proxy protocol needs much less than this. 1024 would be ok. Other options are
191 * - Default ethernet MTU - Eth-II - IP - UDP: 1,514 - 14 - 20 - 8 = 1472 bytes;
192 * - Default token ring MTU 4,202 - overheads = ??.
193 * It would be really more efficient if the final object was less than
194 * a page (4096 bytes) in size.
196 //const unsigned int PROXY_BUFFER_SIZE = 1024;
197 const unsigned int PROXY_BUFFER_SIZE = 5*1024;
199 enum CProxyCommand {
200 PROXY_CMD_CONNECT,
201 PROXY_CMD_BIND,
202 PROXY_CMD_UDP_ASSOCIATE
205 enum CProxyState {
206 PROXY_STATE_START = 0,
207 PROXY_STATE_END = 1
211 * The ProxyStateMachine class is the ancestor of all proxy classes.
213 * CProxyStateMachine will do all the common work that a proxy class must do
214 * and provide the necessary variables.
216 class CProxyStateMachine : public CStateMachine
218 public:
220 * Constructor.
222 * @param name The name of the state machine. For debug messages only.
223 * @param max_states The maximum number of states that this machine will have.
224 * @param proxyData The necessary proxy information.
225 * @param cmd The type of proxy command to run.
227 CProxyStateMachine(
228 wxString name,
229 const unsigned int max_states,
230 const CProxyData &proxyData,
231 CProxyCommand cmd);
233 * Destructor.
235 virtual ~CProxyStateMachine();
237 * Adds a small string to the state machine name, containing the proxy command.
239 * @param s The original state machine name.
240 * @param cmd The proxy command.
242 static wxString &NewName(wxString &s, CProxyCommand cmd);
244 /* Interface */
245 bool Start(const wxIPaddress &peerAddress, wxSocketClient *proxyClientSocket);
246 t_sm_state HandleEvent(t_sm_event event);
247 void AddDummyEvent();
248 void ReactivateSocket();
249 char *GetBuffer() { return m_buffer; }
250 wxIPaddress &GetProxyBoundAddress(void) const { return *m_proxyBoundAddress; }
251 unsigned char GetLastReply(void) const { return m_lastReply; }
252 bool IsEndState() const { return GetState() == PROXY_STATE_END; }
254 protected:
255 wxSocketBase &ProxyWrite(wxSocketBase &socket, const void *buffer, wxUint32 nbytes);
256 wxSocketBase &ProxyRead(wxSocketBase &socket, void *buffer);
257 #ifndef AMULE_DAEMON
258 bool CanReceive() const { return m_canReceive; };
259 bool CanSend() const { return m_canSend; };
260 #else
261 bool CanReceive() const { return true; };
262 bool CanSend() const { return true; };
263 #endif
265 // Initialized at constructor
267 const CProxyData &m_proxyData;
268 CProxyCommand m_proxyCommand;
270 // Member variables
272 char m_buffer[PROXY_BUFFER_SIZE];
273 bool m_isLost;
274 bool m_isConnected;
275 bool m_canReceive;
276 bool m_canSend;
277 bool m_ok;
278 unsigned int m_lastRead;
279 unsigned int m_lastWritten;
280 wxSocketError m_lastError;
282 // Will be initialized at Start()
284 wxIPaddress *m_peerAddress;
285 wxSocketClient *m_proxyClientSocket;
286 wxIPaddress *m_proxyBoundAddress;
287 amuleIPV4Address m_proxyBoundAddressIPV4;
288 //wxIPV6address m_proxyBoundAddressIPV6;
290 // Temporary variables
292 unsigned char m_lastReply;
293 unsigned int m_packetLenght;
296 //------------------------------------------------------------------------------
297 // CSocks5StateMachine
298 //------------------------------------------------------------------------------
299 class CSocks5StateMachine;
300 typedef void (CSocks5StateMachine::*Socks5StateProcessor)(bool entry);
301 class CSocks5StateMachine : public CProxyStateMachine
303 private:
304 static const unsigned int SOCKS5_MAX_STATES = 14;
306 enum Socks5State {
307 SOCKS5_STATE_START = PROXY_STATE_START,
308 SOCKS5_STATE_END = PROXY_STATE_END,
309 SOCKS5_STATE_SEND_QUERY_AUTHENTICATION_METHOD,
310 SOCKS5_STATE_RECEIVE_AUTHENTICATION_METHOD,
311 SOCKS5_STATE_PROCESS_AUTHENTICATION_METHOD,
312 SOCKS5_STATE_SEND_AUTHENTICATION_GSSAPI,
313 SOCKS5_STATE_RECEIVE_AUTHENTICATION_GSSAPI,
314 SOCKS5_STATE_PROCESS_AUTHENTICATION_GSSAPI,
315 SOCKS5_STATE_SEND_AUTHENTICATION_USERNAME_PASSWORD,
316 SOCKS5_STATE_RECEIVE_AUTHENTICATION_USERNAME_PASSWORD,
317 SOCKS5_STATE_PROCESS_AUTHENTICATION_USERNAME_PASSWORD,
318 SOCKS5_STATE_SEND_COMMAND_REQUEST,
319 SOCKS5_STATE_RECEIVE_COMMAND_REPLY,
320 SOCKS5_STATE_PROCESS_COMMAND_REPLY
323 public:
324 /* Constructor */
325 CSocks5StateMachine(
326 const CProxyData &proxyData,
327 CProxyCommand proxyCommand);
328 void process_state(t_sm_state state, bool entry);
329 t_sm_state next_state(t_sm_event event);
331 private:
332 /* State Processors */
333 void process_start(bool entry);
334 void process_send_query_authentication_method(bool entry);
335 void process_receive_authentication_method(bool entry);
336 void process_process_authentication_method(bool entry);
337 void process_send_authentication_gssapi(bool entry);
338 void process_receive_authentication_gssapi(bool entry);
339 void process_process_authentication_gssapi(bool entry);
340 void process_send_authentication_username_password(bool entry);
341 void process_receive_authentication_username_password(bool entry);
342 void process_process_authentication_username_password(bool entry);
343 void process_send_command_request(bool entry);
344 void process_receive_command_reply(bool entry);
345 void process_process_command_reply(bool entry);
346 void process_end(bool entry);
347 /* Private Vars */
348 Socks5StateProcessor m_process_state[SOCKS5_MAX_STATES];
349 wxString m_state_name[SOCKS5_MAX_STATES];
352 //------------------------------------------------------------------------------
353 // CSocks4StateMachine
354 //------------------------------------------------------------------------------
355 class CSocks4StateMachine;
356 typedef void (CSocks4StateMachine::*Socks4StateProcessor)(bool entry);
357 class CSocks4StateMachine : public CProxyStateMachine
359 private:
360 static const unsigned int SOCKS4_MAX_STATES = 5;
362 enum Socks4State {
363 SOCKS4_STATE_START = PROXY_STATE_START,
364 SOCKS4_STATE_END = PROXY_STATE_END,
365 SOCKS4_STATE_SEND_COMMAND_REQUEST,
366 SOCKS4_STATE_RECEIVE_COMMAND_REPLY,
367 SOCKS4_STATE_PROCESS_COMMAND_REPLY
370 public:
371 /* Constructor */
372 CSocks4StateMachine(
373 const CProxyData &proxyData,
374 CProxyCommand proxyCommand);
375 void process_state(t_sm_state state, bool entry);
376 t_sm_state next_state(t_sm_event event);
378 private:
379 /* State Processors */
380 void process_start(bool entry);
381 void process_send_command_request(bool entry);
382 void process_receive_command_reply(bool entry);
383 void process_process_command_reply(bool entry);
384 void process_end(bool entry);
385 /* Private Vars */
386 Socks4StateProcessor m_process_state[SOCKS4_MAX_STATES];
387 wxString m_state_name[SOCKS4_MAX_STATES];
390 //------------------------------------------------------------------------------
391 // CHttpStateMachine
392 //------------------------------------------------------------------------------
393 class CHttpStateMachine;
394 typedef void (CHttpStateMachine::*HttpStateProcessor)(bool entry);
395 class CHttpStateMachine : public CProxyStateMachine
397 private:
398 static const unsigned int HTTP_MAX_STATES = 5;
400 enum HttpState {
401 HTTP_STATE_START = PROXY_STATE_START,
402 HTTP_STATE_END = PROXY_STATE_END,
403 HTTP_STATE_SEND_COMMAND_REQUEST,
404 HTTP_STATE_RECEIVE_COMMAND_REPLY,
405 HTTP_STATE_PROCESS_COMMAND_REPLY
408 public:
409 /* Constructor */
410 CHttpStateMachine(
411 const CProxyData &proxyData,
412 CProxyCommand proxyCommand);
413 void process_state(t_sm_state state, bool entry);
414 t_sm_state next_state(t_sm_event event);
416 private:
417 /* State Processors */
418 void process_start(bool entry);
419 void process_send_command_request(bool entry);
420 void process_receive_command_reply(bool entry);
421 void process_process_command_reply(bool entry);
422 void process_end(bool entry);
423 /* Private Vars */
424 HttpStateProcessor m_process_state[HTTP_MAX_STATES];
425 wxString m_state_name[HTTP_MAX_STATES];
428 //------------------------------------------------------------------------------
429 // CProxySocket
430 //------------------------------------------------------------------------------
432 class CDatagramSocketProxy;
434 class CProxySocket : public wxSocketClient
436 friend class CProxyEventHandler;
437 public:
438 /* Constructor */
439 CProxySocket(
440 wxSocketFlags flags = wxSOCKET_NONE,
441 const CProxyData *proxyData = NULL,
442 CProxyCommand proxyCommand = PROXY_CMD_CONNECT,
443 CDatagramSocketProxy *udpSocket = NULL);
445 /* Destructor */
446 ~CProxySocket();
448 /* I know, this is not very good, because SetEventHandler is not
449 * virtual in wxSocketBase, but I need to GetEventHandler in Proxy.cpp,
450 * so...
452 void SetEventHandler(wxEvtHandler &handler, int id = wxID_ANY)
454 m_socketEventHandler = &handler;
455 m_socketEventHandlerId = id;
456 wxSocketClient::SetEventHandler(handler, id);
458 wxEvtHandler *GetEventHandler(void) const { return m_socketEventHandler; }
459 int GetEventHandlerId(void) const { return m_socketEventHandlerId; }
460 void SaveEventHandler(void)
462 m_savedSocketEventHandler = m_socketEventHandler;
463 m_savedSocketEventHandlerId = m_socketEventHandlerId;
465 void RestoreEventHandler(void)
467 m_socketEventHandler = m_savedSocketEventHandler;
468 m_socketEventHandlerId = m_savedSocketEventHandlerId;
469 SetEventHandler(*m_socketEventHandler, m_socketEventHandlerId);
472 /* Interface */
473 void SetProxyData(const CProxyData *proxyData);
474 bool GetUseProxy() const { return m_useProxy; }
475 char *GetBuffer() { return m_proxyStateMachine->GetBuffer(); }
476 wxIPaddress &GetProxyBoundAddress(void) const
477 { return m_proxyStateMachine->GetProxyBoundAddress(); }
478 bool Start(const wxIPaddress &peerAddress);
479 bool ProxyIsCapableOf(CProxyCommand proxyCommand) const;
480 bool ProxyNegotiationIsOver() const { return m_proxyStateMachine->IsEndState(); }
481 CDatagramSocketProxy *GetUDPSocket() const { return m_udpSocket; }
483 private:
484 bool m_useProxy;
485 CProxyData m_proxyData;
486 amuleIPV4Address m_proxyAddress;
487 CProxyStateMachine *m_proxyStateMachine;
488 CDatagramSocketProxy *m_udpSocket;
489 wxEvtHandler *m_socketEventHandler;
490 int m_socketEventHandlerId;
491 wxEvtHandler *m_savedSocketEventHandler;
492 int m_savedSocketEventHandlerId;
495 //------------------------------------------------------------------------------
496 // CSocketClientProxy
497 //------------------------------------------------------------------------------
499 class CSocketClientProxy : public CProxySocket
501 public:
502 /* Constructor */
503 CSocketClientProxy(
504 wxSocketFlags flags = wxSOCKET_NONE,
505 const CProxyData *proxyData = NULL);
507 /* Interface */
508 bool Connect(wxIPaddress &address, bool wait);
509 CSocketClientProxy& Read(void *buffer, wxUint32 nbytes);
510 CSocketClientProxy& Write(const void *buffer, wxUint32 nbytes);
512 private:
513 wxMutex m_socketLocker;
516 //------------------------------------------------------------------------------
517 // CSocketServerProxy
518 //------------------------------------------------------------------------------
520 class CSocketServerProxy : public wxSocketServer
522 public:
523 /* Constructor */
524 CSocketServerProxy(
525 wxIPaddress &address,
526 wxSocketFlags flags = wxSOCKET_NONE,
527 const CProxyData *proxyData = NULL);
529 /* Interface */
530 CSocketServerProxy& Read(void *buffer, wxUint32 nbytes);
531 CSocketServerProxy& Write(const void *buffer, wxUint32 nbytes);
533 private:
534 wxMutex m_socketLocker;
537 //------------------------------------------------------------------------------
538 // CDatagramSocketProxy
539 //------------------------------------------------------------------------------
541 enum UDPOperation {
542 UDP_OPERATION_NONE,
543 UDP_OPERATION_RECV_FROM,
544 UDP_OPERATION_SEND_TO
547 const unsigned int PROXY_UDP_OVERHEAD_IPV4 = 10;
548 const unsigned int PROXY_UDP_OVERHEAD_DOMAIN_NAME = 262;
549 const unsigned int PROXY_UDP_OVERHEAD_IPV6 = 20;
550 const unsigned int PROXY_UDP_MAXIMUM_OVERHEAD = PROXY_UDP_OVERHEAD_DOMAIN_NAME;
552 class CDatagramSocketProxy : public wxDatagramSocket
554 public:
555 /* Constructor */
556 CDatagramSocketProxy(
557 wxIPaddress &address,
558 wxSocketFlags flags = wxSOCKET_NONE,
559 const CProxyData *proxyData = NULL);
561 /* Destructor */
562 ~CDatagramSocketProxy();
564 /* Interface */
565 void SetUDPSocketOk() { m_udpSocketOk = true; }
567 /* wxDatagramSocket Interface */
568 virtual wxDatagramSocket& RecvFrom(
569 wxSockAddress& addr, void* buf, wxUint32 nBytes );
570 virtual wxDatagramSocket& SendTo(
571 wxIPaddress& addr, const void* buf, wxUint32 nBytes );
572 virtual wxUint32 LastCount(void) const;
574 private:
575 bool m_udpSocketOk;
576 CProxySocket m_proxyTCPSocket;
577 enum UDPOperation m_lastUDPOperation;
578 unsigned int m_lastUDPOverhead;
579 wxMutex m_socketLocker;
582 /******************************************************************************/
584 #endif /* __PROXY_H__ */
586 // File_checked_for_headers