Commit 7041992f authored by Liang-Heng Chen's avatar Liang-Heng Chen
Browse files

Bug 1211567 - Enable domain socket support for SOCKS; r=bagder

MozReview-Commit-ID: 9yMFckwPf6C

--HG--
extra : rebase_source : 17f006f17f97f015403153879cd8b50e482cfc8c
parent f67032cc
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -394,6 +394,16 @@ proxy_GetBoolPref(nsIPrefBranch *aPrefBranch,
        aResult = temp;
}

static inline bool
IsHostDomainSocket(const nsACString& aHost)
{
#ifdef XP_UNIX
    return Substring(aHost, 0, 5) == "file:";
#else
    return false;
#endif // XP_UNIX
}

//----------------------------------------------------------------------------

static const int32_t PROXYCONFIG_DIRECT4X = 3;
@@ -619,7 +629,7 @@ nsProtocolProxyService::PrefsChanged(nsIPrefBranch *prefBranch,
        proxy_GetIntPref(prefBranch, PROXY_PREF("ftp_port"), mFTPProxyPort);

    if (!pref || !strcmp(pref, PROXY_PREF("socks")))
        proxy_GetStringPref(prefBranch, PROXY_PREF("socks"), mSOCKSProxyHost);
        proxy_GetStringPref(prefBranch, PROXY_PREF("socks"), mSOCKSProxyTarget);

    if (!pref || !strcmp(pref, PROXY_PREF("socks_port")))
        proxy_GetIntPref(prefBranch, PROXY_PREF("socks_port"), mSOCKSProxyPort);
@@ -1867,8 +1877,9 @@ nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
    uint32_t proxyFlags = 0;

    if ((flags & RESOLVE_PREFER_SOCKS_PROXY) &&
        !mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
      host = &mSOCKSProxyHost;
        !mSOCKSProxyTarget.IsEmpty() &&
        (IsHostDomainSocket(mSOCKSProxyTarget) || mSOCKSProxyPort > 0)) {
      host = &mSOCKSProxyTarget;
      if (mSOCKSProxyVersion == 4)
          type = kProxyType_SOCKS4;
      else
@@ -1904,8 +1915,9 @@ nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
        type = kProxyType_HTTP;
        port = mFTPProxyPort;
    }
    else if (!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
        host = &mSOCKSProxyHost;
    else if (!mSOCKSProxyTarget.IsEmpty() &&
        (IsHostDomainSocket(mSOCKSProxyTarget) || mSOCKSProxyPort > 0)) {
        host = &mSOCKSProxyTarget;
        if (mSOCKSProxyVersion == 4)
            type = kProxyType_SOCKS4;
        else
+3 −2
Original line number Diff line number Diff line
@@ -388,7 +388,8 @@ protected:
    nsCString                    mHTTPSProxyHost;
    int32_t                      mHTTPSProxyPort;

    nsCString                    mSOCKSProxyHost;
    // mSOCKSProxyTarget could be a host or a domain socket path.
    nsCString                    mSOCKSProxyTarget;
    int32_t                      mSOCKSProxyPort;
    int32_t                      mSOCKSProxyVersion;
    bool                         mSOCKSProxyRemoteDNS;
+84 −17
Original line number Diff line number Diff line
@@ -19,8 +19,10 @@
#include "nsIDNSListener.h"
#include "nsICancelable.h"
#include "nsThreadUtils.h"
#include "nsIURL.h"
#include "mozilla/Logging.h"
#include "mozilla/net/DNS.h"
#include "mozilla/unused.h"

using mozilla::LogLevel;
using namespace mozilla::net;
@@ -111,6 +113,54 @@ private:
    PRStatus ReadFromSocket(PRFileDesc *fd);
    PRStatus WriteToSocket(PRFileDesc *fd);

    bool IsHostDomainSocket()
    {
#ifdef XP_UNIX
        nsAutoCString proxyHost;
        mProxy->GetHost(proxyHost);
        return Substring(proxyHost, 0, 5) == "file:";
#else
        return false;
#endif // XP_UNIX
    }

    nsresult SetDomainSocketPath(const nsACString& aDomainSocketPath,
                             NetAddr* aProxyAddr)
    {
#ifdef XP_UNIX
        nsresult rv;
        MOZ_ASSERT(aProxyAddr);

        nsCOMPtr<nsIURL> url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
        if (NS_WARN_IF(NS_FAILED(rv))) {
            return rv;
        }

        if (NS_WARN_IF(NS_FAILED(rv = url->SetSpec(aDomainSocketPath)))) {
            return rv;
        }

        nsAutoCString path;
        if (NS_WARN_IF(NS_FAILED(rv = url->GetPath(path)))) {
            return rv;
        }

        if (sizeof(aProxyAddr->local.path) <= path.Length()) {
            NS_WARNING("domain socket path too long.");
            return NS_ERROR_FAILURE;
        }

        aProxyAddr->raw.family = AF_UNIX;
        strcpy(aProxyAddr->local.path, path.get());

        return NS_OK;
#else
        mozilla::Unused << aProxyAddr;
        mozilla::Unused << aDomainSocketPath;
        return NS_ERROR_NOT_IMPLEMENTED;
#endif
    }

private:
    State     mState;
    uint8_t * mData;
@@ -420,19 +470,29 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
        mVersion = 5;
    }

    nsAutoCString proxyHost;
    mProxy->GetHost(proxyHost);

    int32_t proxyPort;
    mProxy->GetPort(&proxyPort);

    int32_t addresses = 0;
    do {
        if (addresses++)
        if (IsHostDomainSocket()) {
            rv = SetDomainSocketPath(proxyHost, &mInternalProxyAddr);
            if (NS_FAILED(rv)) {
                LOGERROR(("socks: unable to connect to SOCKS proxy, %s",
                         proxyHost.get()));
              return PR_FAILURE;
            }
        } else {
            if (addresses++) {
                mDnsRec->ReportUnusable(proxyPort);
            }

            rv = mDnsRec->GetNextAddr(proxyPort, &mInternalProxyAddr);
            // No more addresses to try? If so, we'll need to bail
            if (NS_FAILED(rv)) {
            nsCString proxyHost;
            mProxy->GetHost(proxyHost);
                LOGERROR(("socks: unable to connect to SOCKS proxy, %s",
                         proxyHost.get()));
                return PR_FAILURE;
@@ -444,6 +504,7 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
              LOGDEBUG(("socks: trying proxy server, %s:%hu",
                       buf, ntohs(mInternalProxyAddr.inet.port)));
            }
        }

        NetAddr proxy = mInternalProxyAddr;
        FixupAddressFamily(fd, &proxy);
@@ -971,6 +1032,12 @@ nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, int16_t oflags)

    switch (mState) {
        case SOCKS_INITIAL:
            if (IsHostDomainSocket()) {
                mState = SOCKS_DNS_COMPLETE;
                mLookupStatus = NS_OK;
                return ConnectToProxy(fd);
            }

            return StartDNS(fd);
        case SOCKS_DNS_IN_PROGRESS:
            PR_SetError(PR_IN_PROGRESS_ERROR, 0);