Use wxFileName for path manipulation
[amule.git] / src / Proxy.h
blob3abb47b57c9358c0765392a4ccacf1b306bbf386
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2004-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2004-2011 Marcelo Roberto 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.
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
33 #include "LibSocket.h"
35 /******************************************************************************/
38 * SOCKS4 protocol implementation according to:
39 * - "SOCKS: A protocol for TCP proxy across firewalls":
40 * amule-root/docs/socks4.protocol
42 const unsigned char SOCKS4_VERSION = 0x04;
44 const unsigned char SOCKS4_CMD_CONNECT = 0x01;
45 const unsigned char SOCKS4_CMD_BIND = 0x02;
47 const unsigned char SOCKS4_REPLY_CODE = 0;
48 const unsigned char SOCKS4_REPLY_GRANTED = 90;
49 const unsigned char SOCKS4_REPLY_FAILED = 91;
50 const unsigned char SOCKS4_REPLY_FAILED_NO_IDENTD = 92;
51 const unsigned char SOCKS4_REPLY_FAILED_DIFFERENT_USERIDS = 93;
54 * SOCKS5 protocol implementation according to:
55 * - RFC-1928: SOCKS Protocol Version 5
56 * - RFC-1929: username/password Authentication for SOCKS V5
58 * Also, for the future :) :
59 * - RFC-1961: GSS-API Authentication Method for SOCKS Version 5
60 * - RFC-1508: Generic Security Service Application Program Interface
61 * - RFC-1509: Genecic Security Service API: C-bindings
65 const unsigned char SOCKS5_VERSION = 0x05;
67 const unsigned char SOCKS5_AUTH_METHOD_NO_AUTH_REQUIRED = 0x00;
68 const unsigned char SOCKS5_AUTH_METHOD_GSSAPI = 0x01;
69 const unsigned char SOCKS5_AUTH_METHOD_USERNAME_PASSWORD = 0x02;
70 const unsigned char SOCKS5_AUTH_METHOD_NO_ACCEPTABLE_METHODS = 0xFF;
72 const unsigned char SOCKS5_AUTH_VERSION_USERNAME_PASSWORD = 0x01;
74 const unsigned char SOCKS5_CMD_CONNECT = 0x01;
75 const unsigned char SOCKS5_CMD_BIND = 0x02;
76 const unsigned char SOCKS5_CMD_UDP_ASSOCIATE = 0x03;
78 const unsigned char SOCKS5_RSV = 0x00;
80 const unsigned char SOCKS5_ATYP_IPV4_ADDRESS = 0x01;
81 const unsigned char SOCKS5_ATYP_DOMAINNAME = 0x03;
82 const unsigned char SOCKS5_ATYP_IPV6_ADDRESS = 0x04;
84 const unsigned char SOCKS5_REPLY_SUCCEED = 0x00;
85 const unsigned char SOCKS5_REPLY_GENERAL_SERVER_FAILURE = 0x01;
86 const unsigned char SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02;
87 const unsigned char SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03;
88 const unsigned char SOCKS5_REPLY_HOST_UNREACHABLE = 0x04;
89 const unsigned char SOCKS5_REPLY_CONNECTION_REFUSED = 0x05;
90 const unsigned char SOCKS5_REPLY_TTL_EXPIRED = 0x06;
91 const unsigned char SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07;
92 const unsigned char SOCKS5_REPLY_ATYP_NOT_SUPPORTED = 0x08;
94 //------------------------------------------------------------------------------
95 // CProxyType
96 //------------------------------------------------------------------------------
99 * These constants must match the integer values saved in the configuration file,
100 * DO NOT CHANGE THIS ORDER!!!
102 enum CProxyType {
103 PROXY_NONE = -1,
104 PROXY_SOCKS5,
105 PROXY_SOCKS4,
106 PROXY_HTTP,
107 PROXY_SOCKS4a
111 //------------------------------------------------------------------------------
112 // CProxyData
113 //------------------------------------------------------------------------------
115 * The ProxyData class will hold information about the proxy server to be used.
117 class CProxyData
119 public:
121 * Default constructor.
123 CProxyData();
125 * Constructor.
127 * @param proxyEnable Whether proxy is enabled or not.
128 * @param proxyType The type of the proxy server.
129 * @param proxyHostName The proxy host name or IP address.
130 * @param proxyPort The proxy port number.
131 * @param enablePassword Whether authentication should be performed.
132 * @param userName The user name to authenticate to the server.
133 * @param password The password to authenticate to the server.
135 CProxyData(
136 bool proxyEnable,
137 CProxyType proxyType,
138 const wxString &proxyHostName,
139 unsigned short proxyPort,
140 bool enablePassword,
141 const wxString &userName,
142 const wxString &password
145 * Clears the object contents.
147 void Clear();
149 public:
150 //! Whether proxy is enabled or not.
151 bool m_proxyEnable;
152 //! The type of the proxy server.
153 CProxyType m_proxyType;
154 //! The proxy host name or IP address.
155 wxString m_proxyHostName;
156 //! The proxy port number.
157 unsigned short m_proxyPort;
158 //! Whether authentication should be performed.
159 bool m_enablePassword;
160 //! The user name to authenticate to the server.
161 wxString m_userName;
162 //! The password to authenticate to the server.
163 wxString m_password;
166 #ifndef ASIO_SOCKETS
167 //------------------------------------------------------------------------------
168 // CProxyEventHandler
169 //------------------------------------------------------------------------------
171 * Event handler object used during proxy negotiation.
173 class CProxyEventHandler : public wxEvtHandler {
174 public:
176 * Constructor.
178 CProxyEventHandler();
180 private:
182 * Event handler function.
184 void ProxySocketHandler(wxSocketEvent &event);
185 DECLARE_EVENT_TABLE()
187 #endif /* !ASIO_SOCKETS */
189 //------------------------------------------------------------------------------
190 // CProxyStateMachine
191 //------------------------------------------------------------------------------
192 /* This size is just to be a little bit greater than the UDP buffer used in aMule.
193 * Proxy protocol needs much less than this. 1024 would be ok. Other options are
194 * - Default ethernet MTU - Eth-II - IP - UDP: 1,514 - 14 - 20 - 8 = 1472 bytes;
195 * - Default token ring MTU 4,202 - overheads = ??.
196 * It would be really more efficient if the final object was less than
197 * a page (4096 bytes) in size.
199 //const unsigned int PROXY_BUFFER_SIZE = 1024;
200 const unsigned int PROXY_BUFFER_SIZE = 5*1024;
202 enum CProxyCommand {
203 PROXY_CMD_CONNECT,
204 PROXY_CMD_BIND,
205 PROXY_CMD_UDP_ASSOCIATE
208 enum CProxyState {
209 PROXY_STATE_START = 0,
210 PROXY_STATE_END = 1
214 * The ProxyStateMachine class is the ancestor of all proxy classes.
216 * CProxyStateMachine will do all the common work that a proxy class must do
217 * and provide the necessary variables.
219 class CProxyStateMachine : public CStateMachine
221 public:
223 * Constructor.
225 * @param name The name of the state machine. For debug messages only.
226 * @param max_states The maximum number of states that this machine will have.
227 * @param proxyData The necessary proxy information.
228 * @param cmd The type of proxy command to run.
230 CProxyStateMachine(
231 wxString name,
232 const unsigned int max_states,
233 const CProxyData &proxyData,
234 CProxyCommand cmd);
236 * Destructor.
238 virtual ~CProxyStateMachine();
240 * Adds a small string to the state machine name, containing the proxy command.
242 * @param s The original state machine name.
243 * @param cmd The proxy command.
245 static wxString &NewName(wxString &s, CProxyCommand cmd);
247 /* Interface */
248 bool Start(const amuleIPV4Address &peerAddress, CLibSocket *proxyClientSocket);
249 t_sm_state HandleEvent(t_sm_event event);
250 void AddDummyEvent();
251 void ReactivateSocket();
252 char *GetBuffer() { return m_buffer; }
253 amuleIPV4Address &GetProxyBoundAddress(void) const { return *m_proxyBoundAddress; }
254 unsigned char GetLastReply(void) const { return m_lastReply; }
255 bool IsEndState() const { return GetState() == PROXY_STATE_END; }
257 protected:
258 uint32 ProxyWrite(CLibSocket &socket, const void *buffer, wxUint32 nbytes);
259 uint32 ProxyRead(CLibSocket &socket, void *buffer);
260 bool CanReceive() const;
261 bool CanSend() const;
263 // Initialized at constructor
265 const CProxyData &m_proxyData;
266 CProxyCommand m_proxyCommand;
268 // Member variables
270 char m_buffer[PROXY_BUFFER_SIZE];
271 bool m_isLost;
272 bool m_isConnected;
273 bool m_canReceive;
274 bool m_canSend;
275 bool m_ok;
276 unsigned int m_lastRead;
277 int m_lastError;
279 // Will be initialized at Start()
281 amuleIPV4Address *m_peerAddress;
282 CLibSocket *m_proxyClientSocket;
283 amuleIPV4Address *m_proxyBoundAddress;
284 amuleIPV4Address m_proxyBoundAddressIPV4;
285 //wxIPV6address m_proxyBoundAddressIPV6;
287 // Temporary variables
289 unsigned char m_lastReply;
290 unsigned int m_packetLenght;
293 //------------------------------------------------------------------------------
294 // CSocks5StateMachine
295 //------------------------------------------------------------------------------
296 class CSocks5StateMachine;
297 typedef void (CSocks5StateMachine::*Socks5StateProcessor)(bool entry);
298 class CSocks5StateMachine : public CProxyStateMachine
300 private:
301 static const unsigned int SOCKS5_MAX_STATES = 14;
303 enum Socks5State {
304 SOCKS5_STATE_START = PROXY_STATE_START,
305 SOCKS5_STATE_END = PROXY_STATE_END,
306 SOCKS5_STATE_SEND_QUERY_AUTHENTICATION_METHOD,
307 SOCKS5_STATE_RECEIVE_AUTHENTICATION_METHOD,
308 SOCKS5_STATE_PROCESS_AUTHENTICATION_METHOD,
309 SOCKS5_STATE_SEND_AUTHENTICATION_GSSAPI,
310 SOCKS5_STATE_RECEIVE_AUTHENTICATION_GSSAPI,
311 SOCKS5_STATE_PROCESS_AUTHENTICATION_GSSAPI,
312 SOCKS5_STATE_SEND_AUTHENTICATION_USERNAME_PASSWORD,
313 SOCKS5_STATE_RECEIVE_AUTHENTICATION_USERNAME_PASSWORD,
314 SOCKS5_STATE_PROCESS_AUTHENTICATION_USERNAME_PASSWORD,
315 SOCKS5_STATE_SEND_COMMAND_REQUEST,
316 SOCKS5_STATE_RECEIVE_COMMAND_REPLY,
317 SOCKS5_STATE_PROCESS_COMMAND_REPLY
320 public:
321 /* Constructor */
322 CSocks5StateMachine(
323 const CProxyData &proxyData,
324 CProxyCommand proxyCommand);
325 void process_state(t_sm_state state, bool entry);
326 t_sm_state next_state(t_sm_event event);
328 private:
329 /* State Processors */
330 void process_start(bool entry);
331 void process_send_query_authentication_method(bool entry);
332 void process_receive_authentication_method(bool entry);
333 void process_process_authentication_method(bool entry);
334 void process_send_authentication_gssapi(bool entry);
335 void process_receive_authentication_gssapi(bool entry);
336 void process_process_authentication_gssapi(bool entry);
337 void process_send_authentication_username_password(bool entry);
338 void process_receive_authentication_username_password(bool entry);
339 void process_process_authentication_username_password(bool entry);
340 void process_send_command_request(bool entry);
341 void process_receive_command_reply(bool entry);
342 void process_process_command_reply(bool entry);
343 void process_end(bool entry);
344 /* Private Vars */
345 Socks5StateProcessor m_process_state[SOCKS5_MAX_STATES];
346 wxString m_state_name[SOCKS5_MAX_STATES];
349 //------------------------------------------------------------------------------
350 // CSocks4StateMachine
351 //------------------------------------------------------------------------------
352 class CSocks4StateMachine;
353 typedef void (CSocks4StateMachine::*Socks4StateProcessor)(bool entry);
354 class CSocks4StateMachine : public CProxyStateMachine
356 private:
357 static const unsigned int SOCKS4_MAX_STATES = 5;
359 enum Socks4State {
360 SOCKS4_STATE_START = PROXY_STATE_START,
361 SOCKS4_STATE_END = PROXY_STATE_END,
362 SOCKS4_STATE_SEND_COMMAND_REQUEST,
363 SOCKS4_STATE_RECEIVE_COMMAND_REPLY,
364 SOCKS4_STATE_PROCESS_COMMAND_REPLY
367 public:
368 /* Constructor */
369 CSocks4StateMachine(
370 const CProxyData &proxyData,
371 CProxyCommand proxyCommand);
372 void process_state(t_sm_state state, bool entry);
373 t_sm_state next_state(t_sm_event event);
375 private:
376 /* State Processors */
377 void process_start(bool entry);
378 void process_send_command_request(bool entry);
379 void process_receive_command_reply(bool entry);
380 void process_process_command_reply(bool entry);
381 void process_end(bool entry);
382 /* Private Vars */
383 Socks4StateProcessor m_process_state[SOCKS4_MAX_STATES];
384 wxString m_state_name[SOCKS4_MAX_STATES];
387 //------------------------------------------------------------------------------
388 // CHttpStateMachine
389 //------------------------------------------------------------------------------
390 class CHttpStateMachine;
391 typedef void (CHttpStateMachine::*HttpStateProcessor)(bool entry);
392 class CHttpStateMachine : public CProxyStateMachine
394 private:
395 static const unsigned int HTTP_MAX_STATES = 5;
397 enum HttpState {
398 HTTP_STATE_START = PROXY_STATE_START,
399 HTTP_STATE_END = PROXY_STATE_END,
400 HTTP_STATE_SEND_COMMAND_REQUEST,
401 HTTP_STATE_RECEIVE_COMMAND_REPLY,
402 HTTP_STATE_PROCESS_COMMAND_REPLY
405 public:
406 /* Constructor */
407 CHttpStateMachine(
408 const CProxyData &proxyData,
409 CProxyCommand proxyCommand);
410 void process_state(t_sm_state state, bool entry);
411 t_sm_state next_state(t_sm_event event);
413 private:
414 /* State Processors */
415 void process_start(bool entry);
416 void process_send_command_request(bool entry);
417 void process_receive_command_reply(bool entry);
418 void process_process_command_reply(bool entry);
419 void process_end(bool entry);
420 /* Private Vars */
421 HttpStateProcessor m_process_state[HTTP_MAX_STATES];
422 wxString m_state_name[HTTP_MAX_STATES];
425 //------------------------------------------------------------------------------
426 // CProxySocket
427 //------------------------------------------------------------------------------
429 class CDatagramSocketProxy;
431 class CProxySocket : public CLibSocket
433 friend class CProxyEventHandler;
434 public:
435 /* Constructor */
436 CProxySocket(
437 muleSocketFlags flags = MULE_SOCKET_NONE,
438 const CProxyData *proxyData = NULL,
439 CProxyCommand proxyCommand = PROXY_CMD_CONNECT,
440 CDatagramSocketProxy *udpSocket = NULL);
442 /* Destructor */
443 ~CProxySocket();
445 #ifndef ASIO_SOCKETS
446 /* I know, this is not very good, because SetEventHandler is not
447 * virtual in wxSocketBase, but I need to GetEventHandler in Proxy.cpp,
448 * so...
450 void SetEventHandler(wxEvtHandler &handler, int id = wxID_ANY)
452 m_socketEventHandler = &handler;
453 m_socketEventHandlerId = id;
454 CLibSocket::SetEventHandler(handler, id);
456 wxEvtHandler *GetEventHandler(void) const { return m_socketEventHandler; }
457 int GetEventHandlerId(void) const { return m_socketEventHandlerId; }
458 void SaveEventHandler(void)
460 m_savedSocketEventHandler = m_socketEventHandler;
461 m_savedSocketEventHandlerId = m_socketEventHandlerId;
463 void RestoreEventHandler(void)
465 m_socketEventHandler = m_savedSocketEventHandler;
466 m_socketEventHandlerId = m_savedSocketEventHandlerId;
467 SetEventHandler(*m_socketEventHandler, m_socketEventHandlerId);
469 #else
470 // Asio mode
471 virtual void OnProxyEvent(int evt);
472 #endif
474 /* Interface */
475 void SetProxyData(const CProxyData *proxyData);
476 bool GetUseProxy() const { return m_useProxy; }
477 char *GetBuffer() { return m_proxyStateMachine->GetBuffer(); }
478 amuleIPV4Address &GetProxyBoundAddress(void) const
479 { return m_proxyStateMachine->GetProxyBoundAddress(); }
480 bool Start(const amuleIPV4Address &peerAddress);
481 bool ProxyIsCapableOf(CProxyCommand proxyCommand) const;
482 bool ProxyNegotiationIsOver() const { return m_proxyStateMachine->IsEndState(); }
483 CDatagramSocketProxy *GetUDPSocket() const { return m_udpSocket; }
485 private:
486 bool m_useProxy;
487 CProxyData m_proxyData;
488 amuleIPV4Address m_proxyAddress;
489 CProxyStateMachine *m_proxyStateMachine;
490 CDatagramSocketProxy *m_udpSocket;
491 #ifndef ASIO_SOCKETS
492 wxEvtHandler *m_socketEventHandler;
493 int m_socketEventHandlerId;
494 wxEvtHandler *m_savedSocketEventHandler;
495 int m_savedSocketEventHandlerId;
496 #endif
499 //------------------------------------------------------------------------------
500 // CSocketClientProxy
501 //------------------------------------------------------------------------------
503 class CSocketClientProxy : public CProxySocket
505 public:
506 /* Constructor */
507 CSocketClientProxy(
508 muleSocketFlags flags = MULE_SOCKET_NONE,
509 const CProxyData *proxyData = NULL);
511 /* Interface */
512 bool Connect(amuleIPV4Address &address, bool wait);
513 uint32 Read(void *buffer, wxUint32 nbytes);
514 uint32 Write(const void *buffer, wxUint32 nbytes);
516 private:
517 wxMutex m_socketLocker;
520 //------------------------------------------------------------------------------
521 // CSocketServerProxy
522 //------------------------------------------------------------------------------
524 class CSocketServerProxy : public CLibSocketServer
526 public:
527 /* Constructor */
528 CSocketServerProxy(
529 amuleIPV4Address &address,
530 muleSocketFlags flags = MULE_SOCKET_NONE,
531 const CProxyData *proxyData = NULL);
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 CLibUDPSocket
554 public:
555 /* Constructor */
556 CDatagramSocketProxy(
557 amuleIPV4Address &address,
558 muleSocketFlags flags = MULE_SOCKET_NONE,
559 const CProxyData *proxyData = NULL);
561 /* Destructor */
562 ~CDatagramSocketProxy();
564 /* Interface */
565 void SetUDPSocketOk() { m_udpSocketOk = true; }
567 /* wxDatagramSocket Interface */
568 virtual uint32 RecvFrom(amuleIPV4Address& addr, void* buf, uint32 nBytes);
569 virtual uint32 SendTo(const amuleIPV4Address& addr, const void* buf, uint32 nBytes);
571 private:
572 bool m_udpSocketOk;
573 CProxySocket m_proxyTCPSocket;
574 enum UDPOperation m_lastUDPOperation;
575 unsigned int m_lastUDPOverhead;
576 wxMutex m_socketLocker;
579 /******************************************************************************/
581 #endif /* __PROXY_H__ */
583 // File_checked_for_headers