commit cde73b2295b75898ca435ed9f78541eccf6c34cb Author: Liang-Heng Chen xeonchen@mozilla.com Date: Thu Jun 30 11:23:40 2016 +0800
Bug 1211567 - Enable domain socket support for SOCKS; r=bagder
MozReview-Commit-ID: 9yMFckwPf6C
--HG-- extra : rebase_source : 17f006f17f97f015403153879cd8b50e482cfc8c --- netwerk/base/nsProtocolProxyService.cpp | 22 +++++-- netwerk/base/nsProtocolProxyService.h | 5 +- netwerk/socket/nsSOCKSIOLayer.cpp | 101 ++++++++++++++++++++++++++------ 3 files changed, 104 insertions(+), 24 deletions(-)
diff --git a/netwerk/base/nsProtocolProxyService.cpp b/netwerk/base/nsProtocolProxyService.cpp index 593d0af..5d8dc4b 100644 --- a/netwerk/base/nsProtocolProxyService.cpp +++ b/netwerk/base/nsProtocolProxyService.cpp @@ -398,6 +398,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; @@ -623,7 +633,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); @@ -1871,8 +1881,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 @@ -1908,8 +1919,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 diff --git a/netwerk/base/nsProtocolProxyService.h b/netwerk/base/nsProtocolProxyService.h index e9813c8..1e1ea7d 100644 --- a/netwerk/base/nsProtocolProxyService.h +++ b/netwerk/base/nsProtocolProxyService.h @@ -382,8 +382,9 @@ 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; diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp index 568c700..b26408d 100644 --- a/netwerk/socket/nsSOCKSIOLayer.cpp +++ b/netwerk/socket/nsSOCKSIOLayer.cpp @@ -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; @@ -113,6 +115,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; @@ -422,29 +472,40 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd) mVersion = 5; }
+ nsAutoCString proxyHost; + mProxy->GetHost(proxyHost); + int32_t proxyPort; mProxy->GetPort(&proxyPort);
int32_t addresses = 0; do { - 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; - } + 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)) { + LOGERROR(("socks: unable to connect to SOCKS proxy, %s", + proxyHost.get())); + return PR_FAILURE; + }
- if (MOZ_LOG_TEST(gSOCKSLog, LogLevel::Debug)) { - char buf[kIPv6CStrBufSize]; - NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf)); - LOGDEBUG(("socks: trying proxy server, %s:%hu", - buf, ntohs(mInternalProxyAddr.inet.port))); + if (MOZ_LOG_TEST(gSOCKSLog, LogLevel::Debug)) { + char buf[kIPv6CStrBufSize]; + NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf)); + LOGDEBUG(("socks: trying proxy server, %s:%hu", + buf, ntohs(mInternalProxyAddr.inet.port))); + } }
NetAddr proxy = mInternalProxyAddr; @@ -973,6 +1034,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);
tbb-commits@lists.torproject.org