source: filezilla/trunk/fuentes/src/engine/proxy.cpp @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 2 years ago

Update new version: 3.15.02

File size: 19.3 KB
Line 
1#include <wx/defs.h>
2#include <libfilezilla/libfilezilla.hpp>
3#ifdef FZ_WINDOWS
4  #include <libfilezilla/private/windows.hpp>
5  #include <winsock2.h>
6  #include <ws2tcpip.h>
7#else
8  #include <sys/socket.h>
9#endif
10#include <filezilla.h>
11#include "engineprivate.h"
12#include "proxy.h"
13#include "ControlSocket.h"
14
15#include <libfilezilla/iputils.hpp>
16
17#ifndef FZ_WINDOWS
18#include <netdb.h>
19#endif
20
21enum handshake_state
22{
23        http_wait,
24
25        socks5_method,
26        socks5_auth,
27        socks5_request,
28        socks5_request_addrtype,
29        socks5_request_address,
30
31        socks4_handshake
32};
33
34CProxySocket::CProxySocket(fz::event_handler* pEvtHandler, CSocket* pSocket, CControlSocket* pOwner)
35        : fz::event_handler(pOwner->event_loop_)
36        , CBackend(pEvtHandler)
37        , m_pSocket(pSocket)
38        , m_pOwner(pOwner)
39{
40        m_pSocket->SetEventHandler(this);
41}
42
43CProxySocket::~CProxySocket()
44{
45        remove_handler();
46
47        if (m_pSocket)
48                m_pSocket->SetEventHandler(0);
49        delete [] m_pSendBuffer;
50        delete [] m_pRecvBuffer;
51}
52
53namespace {
54wxString base64encode(const wxString& str)
55{
56        // Code shamelessly taken from wxWidgets and adopted to encode UTF-8 strings.
57        // wxWidget's http class encodes string from arbitrary encoding into base64,
58        // could as well encode /dev/random
59        static char const*const base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
60
61        wxString buf;
62
63        const wxWX2MBbuf utf8 = str.mb_str(wxConvUTF8);
64        const char* from = utf8;
65
66        size_t len = strlen(from);
67        while (len >= 3) { // encode full blocks first
68                buf << wxString::Format(wxT("%c%c"), base64[(from[0] >> 2) & 0x3f], base64[((from[0] << 4) & 0x30) | ((from[1] >> 4) & 0xf)]);
69                buf << wxString::Format(wxT("%c%c"), base64[((from[1] << 2) & 0x3c) | ((from[2] >> 6) & 0x3)], base64[from[2] & 0x3f]);
70                from += 3;
71                len -= 3;
72        }
73        if (len > 0) { // pad the remaining characters
74                buf << wxString::Format(wxT("%c"), base64[(from[0] >> 2) & 0x3f]);
75                if (len == 1) {
76                        buf << wxString::Format(wxT("%c="), base64[(from[0] << 4) & 0x30]);
77                }
78                else {
79                        buf << wxString::Format(wxT("%c%c"), base64[((from[0] << 4) & 0x30) | ((from[1] >> 4) & 0xf)], base64[(from[1] << 2) & 0x3c]);
80                }
81                buf << wxString::Format(wxT("="));
82        }
83
84        return buf;
85}
86}
87
88wxString CProxySocket::Name(ProxyType t)
89{
90        switch (t) {
91        case HTTP:
92                return _T("HTTP");
93        case SOCKS4:
94                return _T("SOCKS4");
95        case SOCKS5:
96                return _T("SOCKS5");
97        default:
98                return _("unknown");
99        }
100}
101
102int CProxySocket::Handshake(CProxySocket::ProxyType type, const wxString& host, unsigned int port, const wxString& user, const wxString& pass)
103{
104        if (type == CProxySocket::unknown || host.empty() || port < 1 || port > 65535)
105                return EINVAL;
106
107        if (m_proxyState != noconn)
108                return EALREADY;
109
110        const wxWX2MBbuf host_raw = host.mb_str(wxConvUTF8);
111
112        if (type != HTTP && type != SOCKS5 && type != SOCKS4)
113                return EPROTONOSUPPORT;
114
115        m_user = user;
116        m_pass = pass;
117        m_host = host;
118        m_port = port;
119        m_proxyType = type;
120
121        m_proxyState = handshake;
122
123        if (type == HTTP) {
124                m_handshakeState = http_wait;
125
126                wxWX2MBbuf challenge{};
127                int challenge_len{};
128                if (!user.empty()) {
129                        challenge = base64encode(user + _T(":") + pass).mb_str(wxConvUTF8);
130                        challenge_len = strlen(challenge);
131                }
132
133                // Bit oversized, but be on the safe side
134                m_pSendBuffer = new char[70 + strlen(host_raw) * 2 + 2*5 + challenge_len + 23];
135
136                if (!challenge || !challenge_len) {
137                        m_sendBufferLen = sprintf(m_pSendBuffer, "CONNECT %s:%u HTTP/1.1\r\nHost: %s:%u\r\nUser-Agent: FileZilla\r\n\r\n",
138                                (const char*)host_raw, port,
139                                (const char*)host_raw, port);
140                }
141                else {
142                        m_sendBufferLen = sprintf(m_pSendBuffer, "CONNECT %s:%u HTTP/1.1\r\nHost: %s:%u\r\nProxy-Authorization: Basic %s\r\nUser-Agent: FileZilla\r\n\r\n",
143                                (const char*)host_raw, port,
144                                (const char*)host_raw, port,
145                                (const char*)challenge);
146                }
147
148                m_pRecvBuffer = new char[4096];
149                m_recvBufferLen = 4096;
150                m_recvBufferPos = 0;
151        }
152        else if (type == SOCKS4) {
153                wxString ip = m_host;
154                if (!fz::get_ipv6_long_form(m_host.ToStdWstring()).empty()) {
155                        m_pOwner->LogMessage(MessageType::Error, _("IPv6 addresses are not supported with SOCKS4 proxy"));
156                        return EINVAL;
157                }
158
159                if (fz::get_address_type(m_host.ToStdWstring()) == fz::address_type::unknown) {
160                        addrinfo hints{};
161                        hints.ai_family = AF_INET;
162                        hints.ai_socktype = SOCK_STREAM;
163
164                        addrinfo * result{};
165                        int res = getaddrinfo(host.ToStdString().c_str(), 0, &hints, &result);
166                        if (!res && result) {
167                                if (result->ai_family == AF_INET) {
168                                        ip = CSocket::AddressToString(result->ai_addr, result->ai_addrlen, false);
169                                }
170                                freeaddrinfo(result);
171                        }
172
173                        if (ip.empty()) {
174                                m_pOwner->LogMessage(MessageType::Error, _("Cannot resolve hostname to IPv4 address for use with SOCKS4 proxy."));
175                                return EINVAL;
176                        }
177                }
178
179                m_pOwner->LogMessage(MessageType::Status, _("SOCKS4 proxy will connect to: %s"), ip);
180
181                m_pSendBuffer = new char[9];
182                m_pSendBuffer[0] = 4; // Protocol version
183                m_pSendBuffer[1] = 1; // Stream mode
184                m_pSendBuffer[2] = (m_port >> 8) & 0xFF; // Port in network order
185                m_pSendBuffer[3] = m_port & 0xFF;
186                unsigned char *buf = (unsigned char*)m_pSendBuffer + 4;
187                int i = 0;
188                memset(buf, 0, 4);
189                for (const wxChar* p = ip.c_str(); *p && i < 4; p++) {
190                        const wxChar& c = *p;
191                        if (c == '.') {
192                                i++;
193                                continue;
194                        }
195                        buf[i] *= 10;
196                        buf[i] += c - '0';
197                }
198                m_pSendBuffer[8] = 0;
199                m_sendBufferLen = 9;
200                m_pRecvBuffer = new char[8];
201                m_recvBufferLen = 8;
202                m_recvBufferPos = 0;
203                m_handshakeState = socks4_handshake;
204        }
205        else {
206                m_pSendBuffer = new char[4];
207                m_pSendBuffer[0] = 5; // Protocol version
208                if (!user.empty()) {
209                        m_pSendBuffer[1] = 2; // # auth methods supported
210                        m_pSendBuffer[2] = 0; // Method: No auth
211                        m_pSendBuffer[3] = 2; // Method: Username and password
212                        m_sendBufferLen = 4;
213                }
214                else {
215                        m_pSendBuffer[1] = 1; // # auth methods supported
216                        m_pSendBuffer[2] = 0; // Method: No auth
217                        m_sendBufferLen = 3;
218                }
219
220                m_pRecvBuffer = new char[1024];
221                m_recvBufferLen = 2;
222                m_recvBufferPos = 0;
223
224                m_handshakeState = socks5_method;
225        }
226
227        return EINPROGRESS;
228}
229
230void CProxySocket::operator()(fz::event_base const& ev)
231{
232        fz::dispatch<CSocketEvent, CHostAddressEvent>(ev, this,
233                &CProxySocket::OnSocketEvent,
234                &CProxySocket::OnHostAddress);
235}
236
237void CProxySocket::OnSocketEvent(CSocketEventSource*, SocketEventType t, int error)
238{
239        switch (t) {
240        case SocketEventType::connection_next:
241                if (error)
242                        m_pOwner->LogMessage(MessageType::Status, _("Connection attempt failed with \"%s\", trying next address."), CSocket::GetErrorDescription(error));
243                break;
244        case SocketEventType::connection:
245                if (error) {
246                        if (m_proxyState == handshake)
247                                m_proxyState = noconn;
248                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::connection, error);
249                }
250                else {
251                        m_pOwner->LogMessage(MessageType::Status, _("Connection with proxy established, performing handshake..."));
252                }
253                break;
254        case SocketEventType::read:
255                OnReceive();
256                break;
257        case SocketEventType::write:
258                OnSend();
259                break;
260        case SocketEventType::close:
261                OnReceive();
262                break;
263        }
264}
265
266void CProxySocket::OnHostAddress(CSocketEventSource*, wxString const& address)
267{
268        m_pOwner->LogMessage(MessageType::Status, _("Connecting to %s..."), address);
269}
270
271void CProxySocket::Detach()
272{
273        if (!m_pSocket)
274                return;
275
276        m_pSocket->SetEventHandler(0);
277        m_pSocket = 0;
278}
279
280void CProxySocket::OnReceive()
281{
282        m_can_read = true;
283
284        if (m_proxyState != handshake)
285                return;
286
287        switch (m_handshakeState)
288        {
289        case http_wait:
290                for (;;) {
291                        int error;
292                        int do_read = m_recvBufferLen - m_recvBufferPos - 1;
293                        char* end = 0;
294                        for (int i = 0; i < 2; ++i) {
295                                int read;
296                                if (!i)
297                                        read = m_pSocket->Peek(m_pRecvBuffer + m_recvBufferPos, do_read, error);
298                                else
299                                        read = m_pSocket->Read(m_pRecvBuffer + m_recvBufferPos, do_read, error);
300                                if (read == -1) {
301                                        if (error != EAGAIN) {
302                                                m_proxyState = noconn;
303                                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, error);
304                                        }
305                                        else
306                                                m_can_read = false;
307                                        return;
308                                }
309                                if (!read) {
310                                        m_proxyState = noconn;
311                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
312                                        return;
313                                }
314                                if (m_pSendBuffer) {
315                                        m_proxyState = noconn;
316                                        m_pOwner->LogMessage(MessageType::Debug_Warning, _T("Incoming data before request fully sent"));
317                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
318                                        return;
319                                }
320
321                                if (!i) {
322                                        // Response ends with strstr
323                                        m_pRecvBuffer[m_recvBufferPos + read] = 0;
324                                        end = strstr(m_pRecvBuffer, "\r\n\r\n");
325                                        if (!end) {
326                                                if (m_recvBufferPos + read + 1 == m_recvBufferLen) {
327                                                        m_proxyState = noconn;
328                                                        m_pOwner->LogMessage(MessageType::Debug_Warning, _T("Incoming header too large"));
329                                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ENOMEM);
330                                                        return;
331                                                }
332                                                do_read = read;
333                                        }
334                                        else
335                                                do_read = end - m_pRecvBuffer + 4 - m_recvBufferPos;
336                                }
337                                else {
338                                        if (read != do_read) {
339                                                m_proxyState = noconn;
340                                                m_pOwner->LogMessage(MessageType::Debug_Warning, _T("Could not read what got peeked"));
341                                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
342                                                return;
343                                        }
344                                        m_recvBufferPos += read;
345                                }
346                        }
347
348                        if (!end)
349                                continue;
350
351                        end = strchr(m_pRecvBuffer, '\r'); // Never fails as old value of end exists and starts with CR, we just look for an earlier case.
352                        *end = 0;
353                        wxString reply(m_pRecvBuffer, wxConvUTF8);
354                        m_pOwner->LogMessage(MessageType::Response, _("Proxy reply: %s"), reply);
355
356                        if (reply.Left(10) != _T("HTTP/1.1 2") && reply.Left(10) != _T("HTTP/1.0 2")) {
357                                m_proxyState = noconn;
358                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNRESET);
359                                return;
360                        }
361
362                        m_proxyState = conn;
363                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::connection, 0);
364                        return;
365                }
366        case socks4_handshake:
367                while (m_recvBufferLen && m_can_read && m_proxyState == handshake) {
368                        int read_error;
369                        int read = m_pSocket->Read(m_pRecvBuffer + m_recvBufferPos, m_recvBufferLen, read_error);
370                        if (read == -1) {
371                                if (read_error != EAGAIN) {
372                                        m_proxyState = noconn;
373                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, read_error);
374                                }
375                                else
376                                        m_can_read = false;
377                                return;
378                        }
379
380                        if (!read) {
381                                m_proxyState = noconn;
382                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
383                                return;
384                        }
385                        m_recvBufferPos += read;
386                        m_recvBufferLen -= read;
387
388                        if (m_recvBufferLen)
389                                continue;
390
391                        m_recvBufferPos = 0;
392
393                        if (m_pRecvBuffer[1] != 0x5A) {
394                                wxString error;
395                                switch (m_pRecvBuffer[1]) {
396                                        case 0x5B:
397                                                error = _("Request rejected or failed");
398                                                break;
399                                        case 0x5C:
400                                                error = _("Request failed - client is not running identd (or not reachable from server)");
401                                                break;
402                                        case 0x5D:
403                                                error = _("Request failed - client's identd could not confirm the user ID string");
404                                                break;
405                                        default:
406                                                error.Printf(_("Unassigned error code %d"), (int)(unsigned char) m_pRecvBuffer[1]);
407                                                break;
408                                }
409                                m_pOwner->LogMessage(MessageType::Error, _("Proxy request failed: %s"), error);
410                                m_proxyState = noconn;
411                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
412                                return;
413                        }
414                        m_proxyState = conn;
415                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::connection, 0);
416                }
417                return;
418        case socks5_method:
419        case socks5_auth:
420        case socks5_request:
421        case socks5_request_addrtype:
422        case socks5_request_address:
423                if (m_pSendBuffer)
424                        return;
425                while (m_recvBufferLen && m_can_read && m_proxyState == handshake) {
426                        int error;
427                        int read = m_pSocket->Read(m_pRecvBuffer + m_recvBufferPos, m_recvBufferLen, error);
428                        if (read == -1) {
429                                if (error != EAGAIN) {
430                                        m_proxyState = noconn;
431                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, error);
432                                }
433                                else
434                                        m_can_read = false;
435                                return;
436                        }
437                        if (!read) {
438                                m_proxyState = noconn;
439                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
440                                return;
441                        }
442                        m_recvBufferPos += read;
443                        m_recvBufferLen -= read;
444
445                        if (m_recvBufferLen)
446                                continue;
447
448                        m_recvBufferPos = 0;
449
450                        // All data got read, parse it
451                        switch (m_handshakeState) {
452                        default:
453                                if (m_pRecvBuffer[0] != 5) {
454                                        m_pOwner->LogMessage(MessageType::Error, _("Unknown SOCKS protocol version: %d"), (int)m_pRecvBuffer[0]);
455                                        m_proxyState = noconn;
456                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
457                                        return;
458                                }
459                                break;
460                        case socks5_auth:
461                                if (m_pRecvBuffer[0] != 1) {
462                                        m_pOwner->LogMessage(MessageType::Error, _("Unknown protocol version of SOCKS Username/Password Authentication subnegotiation: %d"), (int)m_pRecvBuffer[0]);
463                                        m_proxyState = noconn;
464                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
465                                        return;
466                                }
467                                break;
468                        case socks5_request_address:
469                        case socks5_request_addrtype:
470                                // Nothing to do
471                                break;
472                        }
473                        switch (m_handshakeState) {
474                        case socks5_method:
475                                {
476                                        const char method = m_pRecvBuffer[1];
477                                        switch (method)
478                                        {
479                                        case 0:
480                                                m_handshakeState = socks5_request;
481                                                break;
482                                        case 2:
483                                                m_handshakeState = socks5_auth;
484                                                break;
485                                        default:
486                                                m_pOwner->LogMessage(MessageType::Error, _("No supported SOCKS5 auth method"));
487                                                m_proxyState = noconn;
488                                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
489                                                return;
490                                        }
491                                }
492                                break;
493                        case socks5_auth:
494                                if (m_pRecvBuffer[1] != 0)
495                                {
496                                        m_pOwner->LogMessage(MessageType::Error, _("Proxy authentication failed"));
497                                        m_proxyState = noconn;
498                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
499                                        return;
500                                }
501                                m_handshakeState = socks5_request;
502                                break;
503                        case socks5_request:
504                                if (m_pRecvBuffer[1]) {
505                                        wxString errorMsg;
506                                        switch (m_pRecvBuffer[1])
507                                        {
508                                        case 1:
509                                                errorMsg = _("General SOCKS server failure");
510                                                break;
511                                        case 2:
512                                                errorMsg = _("Connection not allowed by ruleset");
513                                                break;
514                                        case 3:
515                                                errorMsg = _("Network unreachable");
516                                                break;
517                                        case 4:
518                                                errorMsg = _("Host unreachable");
519                                                break;
520                                        case 5:
521                                                errorMsg = _("Connection refused");
522                                                break;
523                                        case 6:
524                                                errorMsg = _("TTL expired");
525                                                break;
526                                        case 7:
527                                                errorMsg = _("Command not supported");
528                                                break;
529                                        case 8:
530                                                errorMsg = _("Address type not supported");
531                                                break;
532                                        default:
533                                                errorMsg.Printf(_("Unassigned error code %d"), (int)(unsigned char)m_pRecvBuffer[1]);
534                                                break;
535                                        }
536
537                                        m_pOwner->LogMessage(MessageType::Error, _("Proxy request failed. Reply from proxy: %s"), errorMsg);
538                                        m_proxyState = noconn;
539                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
540                                        return;
541                                }
542                                m_handshakeState = socks5_request_addrtype;
543                                m_recvBufferLen = 3;
544                                break;
545                        case socks5_request_addrtype:
546                                // We need to parse the returned address type to determine the length of the address that follows.
547                                // Unfortunately the information in the type and address is useless, many proxies just return
548                                // syntactically valid bogus values
549                                switch (m_pRecvBuffer[1])
550                                {
551                                case 1:
552                                        m_recvBufferLen = 5;
553                                        break;
554                                case 3:
555                                        m_recvBufferLen = m_pRecvBuffer[2] + 2;
556                                        break;
557                                case 4:
558                                        m_recvBufferLen = 17;
559                                        break;
560                                default:
561                                        m_pOwner->LogMessage(MessageType::Error, _("Proxy request failed: Unknown address type in CONNECT reply"));
562                                        m_proxyState = noconn;
563                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
564                                        return;
565                                }
566                                m_handshakeState = socks5_request_address;
567                                break;
568                        case socks5_request_address:
569                                {
570                                        // We're done
571                                        m_proxyState = conn;
572                                        m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::connection, 0);
573                                        return;
574                                }
575                        default:
576                                wxFAIL;
577                                break;
578                        }
579
580                        switch (m_handshakeState)
581                        {
582                        case socks5_auth:
583                                {
584                                        const wxWX2MBbuf user = m_user.mb_str(wxConvUTF8);
585                                        const wxWX2MBbuf pass = m_pass.mb_str(wxConvUTF8);
586
587                                        const int userlen = strlen(user);
588                                        const int passlen = strlen(pass);
589                                        m_sendBufferLen = userlen + passlen + 3;
590                                        m_pSendBuffer = new char[m_sendBufferLen];
591                                        m_pSendBuffer[0] = 1;
592                                        m_pSendBuffer[1] = userlen;
593                                        memcpy(m_pSendBuffer + 2, (const char*)user, userlen);
594                                        m_pSendBuffer[userlen + 2] = passlen;
595                                        memcpy(m_pSendBuffer + userlen + 3, (const char*)pass, passlen);
596                                        m_recvBufferLen = 2;
597                                }
598                                break;
599                        case socks5_request:
600                                {
601                                        const wxWX2MBbuf host = m_host.mb_str(wxConvUTF8);
602                                        const int hostlen = strlen(host);
603                                        int addrlen = wxMax(hostlen, 16);
604
605                                        m_pSendBuffer = new char[7 + addrlen];
606                                        m_pSendBuffer[0] = 5;
607                                        m_pSendBuffer[1] = 1; // CONNECT
608                                        m_pSendBuffer[2] = 0; // Reserved
609
610                                        auto type = fz::get_address_type(m_host.ToStdWstring());
611                                        if (type == fz::address_type::ipv6) {
612                                                auto ipv6 = fz::get_ipv6_long_form(m_host.ToStdWstring());
613                                                addrlen = 16;
614                                                for (int i = 0; i < 16; ++i) {
615                                                        m_pSendBuffer[4 + i] = (fz::hex_char_to_int(ipv6[i * 2 + i / 2]) << 4) + fz::hex_char_to_int(ipv6[i * 2 + 1 + i / 2]);
616                                                }
617
618                                                m_pSendBuffer[3] = 4; // IPv6
619                                        }
620                                        else if (type == fz::address_type::ipv4) {
621                                                unsigned char *buf = (unsigned char*)m_pSendBuffer + 4;
622                                                int i = 0;
623                                                memset(buf, 0, 4);
624                                                for (const wxChar* p = m_host.c_str(); *p && i < 4; ++p) {
625                                                        const wxChar& c = *p;
626                                                        if (c == '.')
627                                                        {
628                                                                i++;
629                                                                continue;
630                                                        }
631                                                        buf[i] *= 10;
632                                                        buf[i] += c - '0';
633                                                }
634
635                                                addrlen = 4;
636
637                                                m_pSendBuffer[3] = 1; // IPv4
638                                        }
639                                        else {
640                                                m_pSendBuffer[3] = 3; // Domain name
641                                                m_pSendBuffer[4] = hostlen;
642                                                memcpy(m_pSendBuffer + 5, (const char*)host, hostlen);
643                                                addrlen = hostlen + 1;
644                                        }
645
646
647                                        m_pSendBuffer[addrlen + 4] = (m_port >> 8) & 0xFF; // Port in network order
648                                        m_pSendBuffer[addrlen + 5] = m_port & 0xFF;
649
650                                        m_sendBufferLen = 6 + addrlen;
651                                        m_recvBufferLen = 2;
652                                }
653                                break;
654                        case socks5_request_addrtype:
655                        case socks5_request_address:
656                                // Nothing to send, we simply need to wait for more data
657                                break;
658                        default:
659                                wxFAIL;
660                                break;
661                        }
662                        if (m_pSendBuffer && m_can_write)
663                                OnSend();
664                }
665                break;
666        default:
667                m_proxyState = noconn;
668                m_pOwner->LogMessage(MessageType::Debug_Warning, _T("Unhandled handshake state %d"), m_handshakeState);
669                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, ECONNABORTED);
670                return;
671        }
672}
673
674void CProxySocket::OnSend()
675{
676        m_can_write = true;
677        if (m_proxyState != handshake || !m_pSendBuffer)
678                return;
679
680        for (;;) {
681                int error;
682                int written = m_pSocket->Write(m_pSendBuffer, m_sendBufferLen, error);
683                if (written == -1) {
684                        if (error != EAGAIN) {
685                                m_proxyState = noconn;
686                                m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, error);
687                        }
688                        else
689                                m_can_write = false;
690
691                        return;
692                }
693
694                if (written == m_sendBufferLen) {
695                        delete [] m_pSendBuffer;
696                        m_pSendBuffer = 0;
697
698                        if (m_can_read)
699                                OnReceive();
700                        return;
701                }
702                memmove(m_pSendBuffer, m_pSendBuffer + written, m_sendBufferLen - written);
703                m_sendBufferLen -= written;
704        }
705}
706
707int CProxySocket::Read(void *, unsigned int, int& error)
708{
709        error = EAGAIN;
710        return -1;
711}
712
713int CProxySocket::Peek(void *, unsigned int, int& error)
714{
715        error = EAGAIN;
716        return -1;
717}
718
719int CProxySocket::Write(const void *, unsigned int, int& error)
720{
721        error = EAGAIN;
722        return -1;
723}
Note: See TracBrowser for help on using the repository browser.