commit cde73b2295b75898ca435ed9f78541eccf6c34cb
Author: Liang-Heng Chen <xeonchen(a)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);