Ticket #8048: 8084.patch

File 8084.patch, 7.3 KB (added by Tautvydas Andrikys, 11 years ago)

Updated implementation

  • src/engine/proxy.cpp

    # HG changeset patch
    # User esminis@esminis
    # Date 1359501956 -7200
    # Node ID a312537b578938b90d44709b37ecb0809a653950
    # Parent  c915a6d4a543533db19fd62d3fddb51d3b6226dc
    #8048 Support SOCKS 4
    
    diff -r c915a6d4a543 -r a312537b5789 src/engine/proxy.cpp
    a b  
    22#include "proxy.h"
    33#include <errno.h>
    44#include "ControlSocket.h"
     5#include <wx/sckaddr.h>
    56
    67enum handshake_state
    78{
     
    1112    socks5_auth,
    1213    socks5_request,
    1314    socks5_request_addrtype,
    14     socks5_request_address
     15    socks5_request_address,
     16
     17    socks4_handshake
    1518};
    1619
    1720CProxySocket::CProxySocket(CSocketEventHandler* pEvtHandler, CSocket* pSocket, CControlSocket* pOwner)
     
    8184
    8285    const wxWX2MBbuf host_raw = host.mb_str(wxConvUTF8);
    8386
    84     if (type != HTTP && type != SOCKS5)
     87    if (type != HTTP && type != SOCKS5 && type != SOCKS4)
    8588        return EPROTONOSUPPORT;
    8689
    8790    m_user = user;
     
    134137        m_recvBufferLen = 4096;
    135138        m_recvBufferPos = 0;
    136139    }
     140    else if (type == SOCKS4)
     141    {
     142        wxString ip = m_host;
     143        if (!IsIpAddress(m_host)) {         
     144            wxIPV4address address;
     145            address.Hostname(host);
     146            ip = address.IPAddress();
     147        }   else if (!GetIPV6LongForm(m_host).empty()) {
     148            m_pOwner->LogMessage(Error, _("IPv6 addresses are not supported with SOCKS4 proxy"));
     149            return EINVAL;
     150        }
     151        m_pOwner->LogMessage(Status, _("SOCKS4 proxy will connect to: %s"), ip.c_str());       
     152       
     153        m_pSendBuffer = new char[9];
     154        m_pSendBuffer[0] = 4; // Protocol version
     155        m_pSendBuffer[1] = 1; // Stream mode
     156        m_pSendBuffer[2] = (m_port >> 8) & 0xFF; // Port in network order
     157        m_pSendBuffer[3] = m_port & 0xFF;
     158        unsigned char *buf = (unsigned char*)m_pSendBuffer + 4;
     159        int i = 0;
     160        memset(buf, 0, 4);
     161        for (const wxChar* p = ip.c_str(); *p; p++) {
     162            const wxChar& c = *p;
     163            if (c == '.') {
     164                i++;
     165                continue;
     166            }
     167            buf[i] *= 10;
     168            buf[i] += c - '0';
     169        }
     170        m_pSendBuffer[8] = 0;
     171        m_sendBufferLen = 9;       
     172        m_pRecvBuffer = new char[8];
     173        m_recvBufferLen = 8;
     174        m_recvBufferPos = 0;
     175        m_handshakeState = socks4_handshake;
     176    }
    137177    else
    138178    {
    139179        m_pSendBuffer = new char[4];
     
    321361            CSocketEventDispatcher::Get().SendEvent(evt);
    322362            return;
    323363        }
     364    case socks4_handshake:
     365        while (m_recvBufferLen && m_can_read && m_proxyState == handshake)
     366        {
     367            int read_error;
     368            int read = m_pSocket->Read(m_pRecvBuffer + m_recvBufferPos, m_recvBufferLen, read_error);
     369            if (read == -1)
     370            {
     371                if (read_error != EAGAIN)
     372                {
     373                    m_proxyState = noconn;
     374                    CSocketEvent *evt = new CSocketEvent(m_pEvtHandler, this, CSocketEvent::close, read_error);
     375                    CSocketEventDispatcher::Get().SendEvent(evt);
     376                }
     377                else
     378                    m_can_read = false;
     379                return;
     380            }
     381           
     382            if (!read)
     383            {
     384                m_proxyState = noconn;
     385                CSocketEvent *evt = new CSocketEvent(m_pEvtHandler, this, CSocketEvent::close, ECONNABORTED);
     386                CSocketEventDispatcher::Get().SendEvent(evt);
     387                return;
     388            }
     389            m_recvBufferPos += read;
     390            m_recvBufferLen -= read;
     391
     392            if (m_recvBufferLen)
     393                continue;
     394
     395            m_recvBufferPos = 0;
     396           
     397            if (m_pRecvBuffer[1] != 0x5A) {
     398                wxString error;
     399                switch (m_pRecvBuffer[1]) {
     400                    case 0x5B:
     401                        error = _("Request rejected or failed");
     402                        break;
     403                    case 0x5C:
     404                        error = _("Request failed - client is not running identd (or not reachable from server)");
     405                        break;
     406                    case 0x5D:
     407                        error = _("Request failed - client's identd could not confirm the user ID string");
     408                        break;             
     409                    default:
     410                        error.Printf(_("Unassigned error code %d"), (int)(unsigned char) m_pRecvBuffer[1]);
     411                        break;
     412                }
     413                m_pOwner->LogMessage(Error, _("Proxy request failed: %s"), error.c_str());
     414                m_proxyState = noconn;
     415                CSocketEventDispatcher::Get()
     416                    .SendEvent(new CSocketEvent(m_pEvtHandler, this, CSocketEvent::close, ECONNABORTED));
     417                return;
     418            }
     419            m_proxyState = conn;
     420            CSocketEventDispatcher::Get()
     421                .SendEvent(new CSocketEvent(m_pEvtHandler, this, CSocketEvent::connection, 0));
     422        }
     423        return;
    324424    case socks5_method:
    325425    case socks5_auth:
    326426    case socks5_request:
  • src/engine/proxy.h

    diff -r c915a6d4a543 -r a312537b5789 src/engine/proxy.h
    a b  
    2222        unknown,
    2323        HTTP,
    2424        SOCKS5,
     25        SOCKS4,
    2526
    2627        proxytype_count
    2728    };
  • src/engine/sftpcontrolsocket.cpp

    diff -r c915a6d4a543 -r a312537b5789 src/engine/sftpcontrolsocket.cpp
    a b  
    549549            case CProxySocket::SOCKS5:
    550550                type = 2;
    551551                break;
     552            case CProxySocket::SOCKS4:
     553                type = 3;
     554                break;
    552555            default:
    553556                LogMessage(__TFILE__, __LINE__, this, Debug_Warning, _T("Unsupported proxy type"));
    554557                DoClose(FZ_REPLY_INTERNALERROR);
  • src/interface/resources/settings.xrc

    diff -r c915a6d4a543 -r a312537b5789 src/interface/resources/settings.xrc
    a b  
    706706                </object>
    707707              </object>
    708708              <object class="sizeritem">
     709                <object class="wxRadioButton" name="ID_PROXYTYPE_SOCKS4">
     710                  <label>SOC&amp;KS 4</label>
     711                </object>
     712              </object>
     713              <object class="sizeritem">
    709714                <object class="wxRadioButton" name="ID_PROXYTYPE_SOCKS5">
    710715                  <label>&amp;SOCKS 5</label>
    711716                </object>
  • src/interface/settings/optionspage_proxy.cpp

    diff -r c915a6d4a543 -r a312537b5789 src/interface/settings/optionspage_proxy.cpp
    a b  
    88BEGIN_EVENT_TABLE(COptionsPageProxy, COptionsPageProxy::COptionsPage)
    99EVT_RADIOBUTTON(XRCID("ID_PROXYTYPE_NONE"), COptionsPageProxy::OnProxyTypeChanged)
    1010EVT_RADIOBUTTON(XRCID("ID_PROXYTYPE_HTTP"), COptionsPageProxy::OnProxyTypeChanged)
     11EVT_RADIOBUTTON(XRCID("ID_PROXYTYPE_SOCKS4"), COptionsPageProxy::OnProxyTypeChanged)
    1112EVT_RADIOBUTTON(XRCID("ID_PROXYTYPE_SOCKS5"), COptionsPageProxy::OnProxyTypeChanged)
    1213END_EVENT_TABLE()
    1314
     
    3334    case 2:
    3435        SetRCheck(XRCID("ID_PROXYTYPE_SOCKS5"), true, failure);
    3536        break;
     37    case 3:
     38        SetRCheck(XRCID("ID_PROXYTYPE_SOCKS4"), true, failure);
     39        break;
    3640    }
    3741
    3842    if (!failure)
     
    5357        type = 1;
    5458    else if (GetRCheck(XRCID("ID_PROXYTYPE_SOCKS5")))
    5559        type = 2;
     60    else if (GetRCheck(XRCID("ID_PROXYTYPE_SOCKS4")))
     61        type = 3;
    5662    else
    5763        type = 0;
    5864    m_pOptions->SetOption(OPTION_PROXY_TYPE, type);
     
    8793void COptionsPageProxy::SetCtrlState()
    8894{
    8995    bool enabled = XRCCTRL(*this, "ID_PROXYTYPE_NONE", wxRadioButton)->GetValue() == 0;
     96    bool enabled_auth = XRCCTRL(*this, "ID_PROXYTYPE_SOCKS4", wxRadioButton)->GetValue() == 0;
    9097
    9198    XRCCTRL(*this, "ID_PROXY_HOST", wxTextCtrl)->Enable(enabled);
    9299    XRCCTRL(*this, "ID_PROXY_PORT", wxTextCtrl)->Enable(enabled);
    93     XRCCTRL(*this, "ID_PROXY_USER", wxTextCtrl)->Enable(enabled);
    94     XRCCTRL(*this, "ID_PROXY_PASS", wxTextCtrl)->Enable(enabled);
     100    XRCCTRL(*this, "ID_PROXY_USER", wxTextCtrl)->Enable(enabled && enabled_auth);
     101    XRCCTRL(*this, "ID_PROXY_PASS", wxTextCtrl)->Enable(enabled && enabled_auth);
    95102}
    96103
    97104void COptionsPageProxy::OnProxyTypeChanged(wxCommandEvent& event)