author | Liang-Heng Chen <xeonchen@mozilla.com> |
Thu, 30 Jun 2016 11:23:40 +0800 (2016-06-30) | |
changeset 311075 | d58a180022cf3405d9683c8a61d9ca7371d8b02a |
parent 311074 | f992cf77d4548ecc1495642741de1534e013e60d |
child 311076 | 687db967e4437a3becb8f32cd3581f192fc237ab |
push id | 30602 |
push user | kwierso@gmail.com |
push date | Thu, 25 Aug 2016 23:53:05 +0000 (2016-08-25) |
treeherder | mozilla-central@cd4ed9909dc9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bagder |
bugs | 1211567 |
milestone | 51.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/netwerk/base/nsProtocolProxyService.cpp +++ b/netwerk/base/nsProtocolProxyService.cpp @@ -389,16 +389,26 @@ proxy_GetBoolPref(nsIPrefBranch *aPrefBr bool temp; nsresult rv = aPrefBranch->GetBoolPref(aPref, &temp); if (NS_FAILED(rv)) aResult = false; else 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; static const int32_t PROXYCONFIG_COUNT = 6; NS_IMPL_ADDREF(nsProtocolProxyService) NS_IMPL_RELEASE(nsProtocolProxyService) NS_IMPL_CLASSINFO(nsProtocolProxyService, nullptr, nsIClassInfo::SINGLETON, @@ -614,17 +624,17 @@ nsProtocolProxyService::PrefsChanged(nsI if (!pref || !strcmp(pref, PROXY_PREF("ftp"))) proxy_GetStringPref(prefBranch, PROXY_PREF("ftp"), mFTPProxyHost); if (!pref || !strcmp(pref, PROXY_PREF("ftp_port"))) 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); if (!pref || !strcmp(pref, PROXY_PREF("socks_version"))) { int32_t version; proxy_GetIntPref(prefBranch, PROXY_PREF("socks_version"), version); // make sure this preference value remains sane @@ -1862,18 +1872,19 @@ nsProtocolProxyService::Resolve_Internal // proxy info values for manual configuration mode const char *type = nullptr; const nsACString *host = nullptr; int32_t port = -1; 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 type = kProxyType_SOCKS; port = mSOCKSProxyPort; if (mSOCKSProxyRemoteDNS) proxyFlags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST; } @@ -1899,18 +1910,19 @@ nsProtocolProxyService::Resolve_Internal } else if (!mFTPProxyHost.IsEmpty() && mFTPProxyPort > 0 && !(flags & RESOLVE_IGNORE_URI_SCHEME) && info.scheme.EqualsLiteral("ftp")) { host = &mFTPProxyHost; 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 type = kProxyType_SOCKS; port = mSOCKSProxyPort; if (mSOCKSProxyRemoteDNS) proxyFlags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST; }
--- a/netwerk/base/nsProtocolProxyService.h +++ b/netwerk/base/nsProtocolProxyService.h @@ -382,18 +382,19 @@ protected: nsCString mHTTPProxyHost; int32_t mHTTPProxyPort; nsCString mFTPProxyHost; int32_t mFTPProxyPort; 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; bool mProxyOverTLS; RefPtr<nsPACMan> mPACMan; // non-null if we are using PAC nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
--- a/netwerk/socket/nsSOCKSIOLayer.cpp +++ b/netwerk/socket/nsSOCKSIOLayer.cpp @@ -14,18 +14,20 @@ #include "nsIDNSRecord.h" #include "nsISOCKSSocketInfo.h" #include "nsISocketProvider.h" #include "nsSOCKSIOLayer.h" #include "nsNetCID.h" #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; static PRDescIdentity nsSOCKSIOLayerIdentity; static PRIOMethods nsSOCKSIOLayerMethods; static bool firstTime = true; static bool ipv6Supported = true; @@ -106,16 +108,64 @@ private: uint32_t ReadUint32(); void ReadNetAddr(NetAddr *addr, uint16_t fam); void ReadNetPort(NetAddr *addr); void WantRead(uint32_t sz); 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; uint8_t * mDataIoPtr; uint32_t mDataLength; uint32_t mReadOffset; uint32_t mAmountToRead; nsCOMPtr<nsIDNSRecord> mDnsRec; @@ -415,39 +465,50 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFile } // Try socks5 if the destination addrress is IPv6 if (mVersion == 4 && mDestinationAddr.raw.family == AF_INET6) { 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); + } - 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))); + 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))); + } } NetAddr proxy = mInternalProxyAddr; FixupAddressFamily(fd, &proxy); PRNetAddr prProxy; NetAddrToPRNetAddr(&proxy, &prProxy); status = fd->lower->methods->connect(fd->lower, &prProxy, mTimeout); if (status != PR_SUCCESS) { @@ -966,16 +1027,22 @@ nsSOCKSSocketInfo::SetConnectTimeout(PRI PRStatus nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, int16_t oflags) { LOGDEBUG(("socks: DoHandshake(), state = %d", mState)); 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); return PR_FAILURE; case SOCKS_DNS_COMPLETE: return ConnectToProxy(fd); case SOCKS_CONNECTING_TO_PROXY: return ContinueConnectingToProxy(fd, oflags);