mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1108957 - Add per network interface dns query. This is possible only with gonk. r=mayhemer
This commit is contained in:
parent
91bb7e982e
commit
bec13a89db
@ -32,6 +32,7 @@ struct DNSCacheEntries
|
||||
nsTArray<nsCString> hostaddr;
|
||||
uint16_t family;
|
||||
int64_t expiration;
|
||||
nsCString netInterface;
|
||||
};
|
||||
|
||||
struct HttpConnInfo
|
||||
|
@ -56,11 +56,15 @@ ChildDNSService::~ChildDNSService()
|
||||
void
|
||||
ChildDNSService::GetDNSRecordHashKey(const nsACString &aHost,
|
||||
uint32_t aFlags,
|
||||
const nsACString &aNetworkInterface,
|
||||
nsIDNSListener* aListener,
|
||||
nsACString &aHashKey)
|
||||
{
|
||||
aHashKey.Assign(aHost);
|
||||
aHashKey.AppendInt(aFlags);
|
||||
if (!aNetworkInterface.IsEmpty()) {
|
||||
aHashKey.Append(aNetworkInterface);
|
||||
}
|
||||
aHashKey.AppendPrintf("%p", aListener);
|
||||
}
|
||||
|
||||
@ -74,6 +78,18 @@ ChildDNSService::AsyncResolve(const nsACString &hostname,
|
||||
nsIDNSListener *listener,
|
||||
nsIEventTarget *target_,
|
||||
nsICancelable **result)
|
||||
{
|
||||
return AsyncResolveExtended(hostname, flags, EmptyCString(), listener,
|
||||
target_, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSService::AsyncResolveExtended(const nsACString &hostname,
|
||||
uint32_t flags,
|
||||
const nsACString &aNetworkInterface,
|
||||
nsIDNSListener *listener,
|
||||
nsIEventTarget *target_,
|
||||
nsICancelable **result)
|
||||
{
|
||||
NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
|
||||
|
||||
@ -108,12 +124,15 @@ ChildDNSService::AsyncResolve(const nsACString &hostname,
|
||||
}
|
||||
|
||||
nsRefPtr<DNSRequestChild> childReq =
|
||||
new DNSRequestChild(nsCString(hostname), flags, listener, target);
|
||||
new DNSRequestChild(nsCString(hostname), flags,
|
||||
nsCString(aNetworkInterface),
|
||||
listener, target);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mPendingRequestsLock);
|
||||
nsCString key;
|
||||
GetDNSRecordHashKey(hostname, originalFlags, originalListener, key);
|
||||
GetDNSRecordHashKey(hostname, originalFlags, aNetworkInterface,
|
||||
originalListener, key);
|
||||
nsTArray<nsRefPtr<DNSRequestChild>> *hashEntry;
|
||||
if (mPendingRequests.Get(key, &hashEntry)) {
|
||||
hashEntry->AppendElement(childReq);
|
||||
@ -135,6 +154,17 @@ ChildDNSService::CancelAsyncResolve(const nsACString &aHostname,
|
||||
uint32_t aFlags,
|
||||
nsIDNSListener *aListener,
|
||||
nsresult aReason)
|
||||
{
|
||||
return CancelAsyncResolveExtended(aHostname, aFlags, EmptyCString(),
|
||||
aListener, aReason);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSService::CancelAsyncResolveExtended(const nsACString &aHostname,
|
||||
uint32_t aFlags,
|
||||
const nsACString &aNetworkInterface,
|
||||
nsIDNSListener *aListener,
|
||||
nsresult aReason)
|
||||
{
|
||||
if (mDisablePrefetch && (aFlags & RESOLVE_SPECULATE)) {
|
||||
return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
|
||||
@ -143,7 +173,7 @@ ChildDNSService::CancelAsyncResolve(const nsACString &aHostname,
|
||||
MutexAutoLock lock(mPendingRequestsLock);
|
||||
nsTArray<nsRefPtr<DNSRequestChild>> *hashEntry;
|
||||
nsCString key;
|
||||
GetDNSRecordHashKey(aHostname, aFlags, aListener, key);
|
||||
GetDNSRecordHashKey(aHostname, aFlags, aNetworkInterface, aListener, key);
|
||||
if (mPendingRequests.Get(key, &hashEntry)) {
|
||||
// We cancel just one.
|
||||
hashEntry->ElementAt(0)->Cancel(aReason);
|
||||
@ -195,7 +225,8 @@ ChildDNSService::NotifyRequestDone(DNSRequestChild *aDnsRequest)
|
||||
MutexAutoLock lock(mPendingRequestsLock);
|
||||
|
||||
nsCString key;
|
||||
GetDNSRecordHashKey(aDnsRequest->mHost, originalFlags, originalListener, key);
|
||||
GetDNSRecordHashKey(aDnsRequest->mHost, originalFlags,
|
||||
aDnsRequest->mNetworkInterface, originalListener, key);
|
||||
|
||||
nsTArray<nsRefPtr<DNSRequestChild>> *hashEntry;
|
||||
|
||||
|
@ -40,6 +40,7 @@ private:
|
||||
|
||||
void MOZ_ALWAYS_INLINE GetDNSRecordHashKey(const nsACString &aHost,
|
||||
uint32_t aFlags,
|
||||
const nsACString &aNetworkInterface,
|
||||
nsIDNSListener* aListener,
|
||||
nsACString &aHashKey);
|
||||
|
||||
|
@ -172,7 +172,8 @@ public:
|
||||
if (mDnsRequest->mIPCOpen) {
|
||||
// Send request to Parent process.
|
||||
mDnsRequest->SendCancelDNSRequest(mDnsRequest->mHost, mDnsRequest->mFlags,
|
||||
mReasonForCancel);
|
||||
mDnsRequest->mNetworkInterface,
|
||||
mReasonForCancel);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -187,6 +188,7 @@ private:
|
||||
|
||||
DNSRequestChild::DNSRequestChild(const nsCString& aHost,
|
||||
const uint32_t& aFlags,
|
||||
const nsCString& aNetworkInterface,
|
||||
nsIDNSListener *aListener,
|
||||
nsIEventTarget *target)
|
||||
: mListener(aListener)
|
||||
@ -194,6 +196,7 @@ DNSRequestChild::DNSRequestChild(const nsCString& aHost,
|
||||
, mResultStatus(NS_OK)
|
||||
, mHost(aHost)
|
||||
, mFlags(aFlags)
|
||||
, mNetworkInterface(aNetworkInterface)
|
||||
, mIPCOpen(false)
|
||||
{
|
||||
}
|
||||
@ -209,7 +212,8 @@ DNSRequestChild::StartRequest()
|
||||
}
|
||||
|
||||
// Send request to Parent process.
|
||||
gNeckoChild->SendPDNSRequestConstructor(this, mHost, mFlags);
|
||||
gNeckoChild->SendPDNSRequestConstructor(this, mHost, mFlags,
|
||||
mNetworkInterface);
|
||||
mIPCOpen = true;
|
||||
|
||||
// IPDL holds a reference until IPDL channel gets destroyed
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
NS_DECL_NSICANCELABLE
|
||||
|
||||
DNSRequestChild(const nsCString& aHost, const uint32_t& aFlags,
|
||||
const nsCString& aNetworkInterface,
|
||||
nsIDNSListener *aListener, nsIEventTarget *target);
|
||||
|
||||
void AddIPDLReference() {
|
||||
@ -50,6 +51,7 @@ protected:
|
||||
nsresult mResultStatus;
|
||||
nsCString mHost;
|
||||
uint16_t mFlags;
|
||||
nsCString mNetworkInterface;
|
||||
bool mIPCOpen;
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,8 @@ DNSRequestParent::~DNSRequestParent()
|
||||
}
|
||||
|
||||
void
|
||||
DNSRequestParent::DoAsyncResolve(const nsACString &hostname, uint32_t flags)
|
||||
DNSRequestParent::DoAsyncResolve(const nsACString &hostname, uint32_t flags,
|
||||
const nsACString &networkInterface)
|
||||
{
|
||||
nsresult rv;
|
||||
mFlags = flags;
|
||||
@ -39,8 +40,8 @@ DNSRequestParent::DoAsyncResolve(const nsACString &hostname, uint32_t flags)
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
nsCOMPtr<nsICancelable> unused;
|
||||
rv = dns->AsyncResolve(hostname, flags, this, mainThread,
|
||||
getter_AddRefs(unused));
|
||||
rv = dns->AsyncResolveExtended(hostname, flags, networkInterface, this,
|
||||
mainThread, getter_AddRefs(unused));
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) && !mIPCClosed) {
|
||||
@ -52,12 +53,14 @@ DNSRequestParent::DoAsyncResolve(const nsACString &hostname, uint32_t flags)
|
||||
bool
|
||||
DNSRequestParent::RecvCancelDNSRequest(const nsCString& hostName,
|
||||
const uint32_t& flags,
|
||||
const nsCString& networkInterface,
|
||||
const nsresult& reason)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = dns->CancelAsyncResolve(hostName, flags, this, reason);
|
||||
rv = dns->CancelAsyncResolveExtended(hostName, flags, networkInterface,
|
||||
this, reason);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -24,12 +24,14 @@ public:
|
||||
|
||||
DNSRequestParent();
|
||||
|
||||
void DoAsyncResolve(const nsACString &hostname, uint32_t flags);
|
||||
void DoAsyncResolve(const nsACString &hostname, uint32_t flags,
|
||||
const nsACString &networkInterface);
|
||||
|
||||
// Pass args here rather than storing them in the parent; they are only
|
||||
// needed if the request is to be canceled.
|
||||
bool RecvCancelDNSRequest(const nsCString& hostName,
|
||||
const uint32_t& flags,
|
||||
const nsCString& networkInterface,
|
||||
const nsresult& reason) MOZ_OVERRIDE;
|
||||
bool Recv__delete__() MOZ_OVERRIDE;
|
||||
|
||||
|
@ -16,6 +16,11 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include <algorithm>
|
||||
#include "prerror.h"
|
||||
|
||||
#if defined(ANDROID) && ANDROID_VERSION > 19
|
||||
#include <resolv_netid.h>
|
||||
#endif
|
||||
|
||||
#include "prlog.h"
|
||||
#if defined(PR_LOGGING)
|
||||
@ -215,13 +220,81 @@ _GetTTLData_Windows(const char* aHost, uint16_t* aResult)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Make the same as nspr functions.
|
||||
static MOZ_ALWAYS_INLINE PRAddrInfo*
|
||||
_Android_GetAddrInfoForNetInterface(const char* hostname,
|
||||
uint16_t af,
|
||||
uint16_t flags,
|
||||
const char* aNetworkInterface)
|
||||
{
|
||||
#if !defined(ANDROID) || ANDROID_VERSION < 19
|
||||
PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, 0);
|
||||
return nullptr;
|
||||
#else
|
||||
if ((af != PR_AF_INET && af != PR_AF_UNSPEC) ||
|
||||
(flags & ~ PR_AI_NOCANONNAME) != PR_AI_ADDRCONFIG) {
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct addrinfo *res, hints;
|
||||
int rv;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
if (!(flags & PR_AI_NOCANONNAME)) {
|
||||
hints.ai_flags |= AI_CANONNAME;
|
||||
}
|
||||
|
||||
#ifdef AI_ADDRCONFIG
|
||||
if ((flags & PR_AI_ADDRCONFIG) &&
|
||||
strcmp(hostname, "localhost") != 0 &&
|
||||
strcmp(hostname, "localhost.localdomain") != 0 &&
|
||||
strcmp(hostname, "localhost6") != 0 &&
|
||||
strcmp(hostname, "localhost6.localdomain6") != 0) {
|
||||
hints.ai_flags |= AI_ADDRCONFIG;
|
||||
}
|
||||
#endif
|
||||
|
||||
hints.ai_family = (af == PR_AF_INET) ? AF_INET : AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
#if ANDROID_VERSION == 19
|
||||
rv = android_getaddrinfoforiface(hostname, NULL, &hints, aNetworkInterface,
|
||||
0, &res);
|
||||
#else
|
||||
uint32_t netId = atoi(aNetworkInterface);
|
||||
rv = android_getaddrinfofornet(hostname, NULL, &hints, netId, 0, &res);
|
||||
#endif
|
||||
|
||||
#ifdef AI_ADDRCONFIG
|
||||
if (rv == EAI_BADFLAGS && (hints.ai_flags & AI_ADDRCONFIG)) {
|
||||
hints.ai_flags &= ~AI_ADDRCONFIG;
|
||||
#if ANDROID_VERSION == 19
|
||||
rv = android_getaddrinfoforiface(hostname, NULL, &hints, aNetworkInterface,
|
||||
0, &res);
|
||||
#else
|
||||
uint32_t netId = atoi(aNetworkInterface);
|
||||
rv = android_getaddrinfofornet(hostname, NULL, &hints, netId, 0, &res);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rv == 0) {
|
||||
return (PRAddrInfo *) res;
|
||||
}
|
||||
|
||||
PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, rv);
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// PORTABLE RUNTIME IMPLEMENTATION//
|
||||
////////////////////////////////////
|
||||
|
||||
static MOZ_ALWAYS_INLINE nsresult
|
||||
_GetAddrInfo_Portable(const char* aCanonHost, uint16_t aAddressFamily,
|
||||
uint16_t aFlags, AddrInfo** aAddrInfo)
|
||||
uint16_t aFlags, const char* aNetworkInterface,
|
||||
AddrInfo** aAddrInfo)
|
||||
{
|
||||
MOZ_ASSERT(aCanonHost);
|
||||
MOZ_ASSERT(aAddrInfo);
|
||||
@ -241,7 +314,18 @@ _GetAddrInfo_Portable(const char* aCanonHost, uint16_t aAddressFamily,
|
||||
aAddressFamily = PR_AF_UNSPEC;
|
||||
}
|
||||
|
||||
PRAddrInfo* prai = PR_GetAddrInfoByName(aCanonHost, aAddressFamily, prFlags);
|
||||
PRAddrInfo* prai;
|
||||
#if defined(ANDROID) && ANDROID_VERSION >= 19
|
||||
if (aNetworkInterface && aNetworkInterface[0] != '\0') {
|
||||
prai = _Android_GetAddrInfoForNetInterface(aCanonHost,
|
||||
aAddressFamily,
|
||||
prFlags,
|
||||
aNetworkInterface);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
prai = PR_GetAddrInfoByName(aCanonHost, aAddressFamily, prFlags);
|
||||
}
|
||||
|
||||
if (!prai) {
|
||||
return NS_ERROR_UNKNOWN_HOST;
|
||||
@ -290,7 +374,7 @@ GetAddrInfoShutdown() {
|
||||
|
||||
nsresult
|
||||
GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags,
|
||||
AddrInfo** aAddrInfo, bool aGetTtl)
|
||||
const char* aNetworkInterface, AddrInfo** aAddrInfo, bool aGetTtl)
|
||||
{
|
||||
if (NS_WARN_IF(!aHost) || NS_WARN_IF(!aAddrInfo)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
@ -304,7 +388,8 @@ GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags,
|
||||
#endif
|
||||
|
||||
*aAddrInfo = nullptr;
|
||||
nsresult rv = _GetAddrInfo_Portable(aHost, aAddressFamily, aFlags, aAddrInfo);
|
||||
nsresult rv = _GetAddrInfo_Portable(aHost, aAddressFamily, aFlags,
|
||||
aNetworkInterface, aAddrInfo);
|
||||
|
||||
#if DNSQUERY_AVAILABLE
|
||||
if (aGetTtl && NS_SUCCEEDED(rv)) {
|
||||
|
@ -40,7 +40,7 @@ class AddrInfo;
|
||||
*/
|
||||
nsresult
|
||||
GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags,
|
||||
AddrInfo** aAddrInfo, bool aGetTtl);
|
||||
const char* aNetworkInterface, AddrInfo** aAddrInfo, bool aGetTtl);
|
||||
|
||||
/**
|
||||
* Initialize the GetAddrInfo module.
|
||||
|
@ -23,7 +23,8 @@ parent:
|
||||
|
||||
// Pass args here rather than storing them in the parent; they are only
|
||||
// needed if the request is to be canceled.
|
||||
CancelDNSRequest(nsCString hostName, uint32_t flags, nsresult reason);
|
||||
CancelDNSRequest(nsCString hostName, uint32_t flags,
|
||||
nsCString networkInterface, nsresult reason);
|
||||
__delete__();
|
||||
|
||||
child:
|
||||
|
@ -67,3 +67,6 @@ etld_data.inputs = ['effective_tld_names.dat']
|
||||
LOCAL_INCLUDES += [
|
||||
'/netwerk/base',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '19':
|
||||
CXXFLAGS += ['-I%s/bionic/libc/dns/include' % CONFIG['ANDROID_SOURCE']]
|
||||
|
@ -303,12 +303,14 @@ public:
|
||||
const nsACString &host,
|
||||
nsIDNSListener *listener,
|
||||
uint16_t flags,
|
||||
uint16_t af)
|
||||
uint16_t af,
|
||||
const nsACString &netInterface)
|
||||
: mResolver(res)
|
||||
, mHost(host)
|
||||
, mListener(listener)
|
||||
, mFlags(flags)
|
||||
, mAF(af) {}
|
||||
, mAF(af)
|
||||
, mNetworkInterface(netInterface) {}
|
||||
|
||||
void OnLookupComplete(nsHostResolver *, nsHostRecord *, nsresult) MOZ_OVERRIDE;
|
||||
// Returns TRUE if the DNS listener arg is the same as the member listener
|
||||
@ -323,6 +325,7 @@ public:
|
||||
nsCOMPtr<nsIDNSListener> mListener;
|
||||
uint16_t mFlags;
|
||||
uint16_t mAF;
|
||||
nsCString mNetworkInterface;
|
||||
};
|
||||
|
||||
void
|
||||
@ -382,7 +385,8 @@ NS_IMETHODIMP
|
||||
nsDNSAsyncRequest::Cancel(nsresult reason)
|
||||
{
|
||||
NS_ENSURE_ARG(NS_FAILED(reason));
|
||||
mResolver->DetachCallback(mHost.get(), mFlags, mAF, this, reason);
|
||||
mResolver->DetachCallback(mHost.get(), mFlags, mAF, mNetworkInterface.get(),
|
||||
this, reason);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -709,6 +713,18 @@ nsDNSService::AsyncResolve(const nsACString &aHostname,
|
||||
nsIDNSListener *listener,
|
||||
nsIEventTarget *target_,
|
||||
nsICancelable **result)
|
||||
{
|
||||
return AsyncResolveExtended(aHostname, flags, EmptyCString(), listener, target_,
|
||||
result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::AsyncResolveExtended(const nsACString &aHostname,
|
||||
uint32_t flags,
|
||||
const nsACString &aNetworkInterface,
|
||||
nsIDNSListener *listener,
|
||||
nsIEventTarget *target_,
|
||||
nsICancelable **result)
|
||||
{
|
||||
// grab reference to global host resolver and IDN service. beware
|
||||
// simultaneous shutdown!!
|
||||
@ -751,13 +767,14 @@ nsDNSService::AsyncResolve(const nsACString &aHostname,
|
||||
}
|
||||
|
||||
if (target) {
|
||||
listener = new DNSListenerProxy(listener, target);
|
||||
listener = new DNSListenerProxy(listener, target);
|
||||
}
|
||||
|
||||
uint16_t af = GetAFForLookup(hostname, flags);
|
||||
|
||||
nsDNSAsyncRequest *req =
|
||||
new nsDNSAsyncRequest(res, hostname, listener, flags, af);
|
||||
new nsDNSAsyncRequest(res, hostname, listener, flags, af,
|
||||
aNetworkInterface);
|
||||
if (!req)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*result = req);
|
||||
@ -767,7 +784,9 @@ nsDNSService::AsyncResolve(const nsACString &aHostname,
|
||||
|
||||
// addref for resolver; will be released when OnLookupComplete is called.
|
||||
NS_ADDREF(req);
|
||||
nsresult rv = res->ResolveHost(req->mHost.get(), flags, af, req);
|
||||
nsresult rv = res->ResolveHost(req->mHost.get(), flags, af,
|
||||
req->mNetworkInterface.get(),
|
||||
req);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(req);
|
||||
NS_RELEASE(*result);
|
||||
@ -780,6 +799,17 @@ nsDNSService::CancelAsyncResolve(const nsACString &aHostname,
|
||||
uint32_t aFlags,
|
||||
nsIDNSListener *aListener,
|
||||
nsresult aReason)
|
||||
{
|
||||
return CancelAsyncResolveExtended(aHostname, aFlags, EmptyCString(), aListener,
|
||||
aReason);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::CancelAsyncResolveExtended(const nsACString &aHostname,
|
||||
uint32_t aFlags,
|
||||
const nsACString &aNetworkInterface,
|
||||
nsIDNSListener *aListener,
|
||||
nsresult aReason)
|
||||
{
|
||||
// grab reference to global host resolver and IDN service. beware
|
||||
// simultaneous shutdown!!
|
||||
@ -805,7 +835,9 @@ nsDNSService::CancelAsyncResolve(const nsACString &aHostname,
|
||||
|
||||
uint16_t af = GetAFForLookup(hostname, aFlags);
|
||||
|
||||
res->CancelAsyncRequest(hostname.get(), aFlags, af, aListener, aReason);
|
||||
res->CancelAsyncRequest(hostname.get(), aFlags, af,
|
||||
nsPromiseFlatCString(aNetworkInterface).get(), aListener,
|
||||
aReason);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -857,7 +889,7 @@ nsDNSService::Resolve(const nsACString &aHostname,
|
||||
|
||||
uint16_t af = GetAFForLookup(hostname, flags);
|
||||
|
||||
nsresult rv = res->ResolveHost(hostname.get(), flags, af, &syncReq);
|
||||
nsresult rv = res->ResolveHost(hostname.get(), flags, af, "", &syncReq);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// wait for result
|
||||
while (!syncReq.mDone)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsISupportsBase.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "prthread.h"
|
||||
#include "prerror.h"
|
||||
#include "prtime.h"
|
||||
@ -75,6 +76,10 @@ static PRLogModuleInfo *gHostResolverLog = nullptr;
|
||||
#define LOG(args)
|
||||
#endif
|
||||
|
||||
#define LOG_HOST(host, interface) host, \
|
||||
(interface && interface[0] != '\0') ? " on interface " : "", \
|
||||
(interface && interface[0] != '\0') ? interface : ""
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static inline void
|
||||
@ -179,7 +184,9 @@ nsHostRecord::nsHostRecord(const nsHostKey *key)
|
||||
memcpy((char *) host, key->host, strlen(key->host) + 1);
|
||||
flags = key->flags;
|
||||
af = key->af;
|
||||
|
||||
netInterface = host + strlen(key->host) + 1;
|
||||
memcpy((char *) netInterface, key->netInterface,
|
||||
strlen(key->netInterface) + 1);
|
||||
PR_INIT_CLIST(this);
|
||||
PR_INIT_CLIST(&callbacks);
|
||||
}
|
||||
@ -188,10 +195,11 @@ nsresult
|
||||
nsHostRecord::Create(const nsHostKey *key, nsHostRecord **result)
|
||||
{
|
||||
size_t hostLen = strlen(key->host) + 1;
|
||||
size_t size = hostLen + sizeof(nsHostRecord);
|
||||
size_t netInterfaceLen = strlen(key->netInterface) + 1;
|
||||
size_t size = hostLen + netInterfaceLen + sizeof(nsHostRecord);
|
||||
|
||||
// Use placement new to create the object with room for the hostname
|
||||
// allocated after it.
|
||||
// Use placement new to create the object with room for the hostname and
|
||||
// network interface name allocated after it.
|
||||
void *place = ::operator new(size);
|
||||
*result = new(place) nsHostRecord(key);
|
||||
NS_ADDREF(*result);
|
||||
@ -231,7 +239,8 @@ bool
|
||||
nsHostRecord::Blacklisted(NetAddr *aQuery)
|
||||
{
|
||||
// must call locked
|
||||
LOG(("Checking blacklist for host [%s], host record [%p].\n", host, this));
|
||||
LOG(("Checking blacklist for host [%s%s%s], host record [%p].\n",
|
||||
LOG_HOST(host, netInterface), this));
|
||||
|
||||
// skip the string conversion for the common case of no blacklist
|
||||
if (!mBlacklistedItems.Length()) {
|
||||
@ -246,7 +255,8 @@ nsHostRecord::Blacklisted(NetAddr *aQuery)
|
||||
|
||||
for (uint32_t i = 0; i < mBlacklistedItems.Length(); i++) {
|
||||
if (mBlacklistedItems.ElementAt(i).Equals(strQuery)) {
|
||||
LOG(("Address [%s] is blacklisted for host [%s].\n", buf, host));
|
||||
LOG(("Address [%s] is blacklisted for host [%s%s%s].\n", buf,
|
||||
LOG_HOST(host, netInterface)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -258,7 +268,8 @@ void
|
||||
nsHostRecord::ReportUnusable(NetAddr *aAddress)
|
||||
{
|
||||
// must call locked
|
||||
LOG(("Adding address to blacklist for host [%s], host record [%p].\n", host, this));
|
||||
LOG(("Adding address to blacklist for host [%s%s%s], host record [%p].\n",
|
||||
LOG_HOST(host, netInterface), this));
|
||||
|
||||
++mBlacklistedCount;
|
||||
|
||||
@ -267,7 +278,8 @@ nsHostRecord::ReportUnusable(NetAddr *aAddress)
|
||||
|
||||
char buf[kIPv6CStrBufSize];
|
||||
if (NetAddrToString(aAddress, buf, sizeof(buf))) {
|
||||
LOG(("Successfully adding address [%s] to blacklist for host [%s].\n", buf, host));
|
||||
LOG(("Successfully adding address [%s] to blacklist for host "
|
||||
"[%s%s%s].\n", buf, LOG_HOST(host, netInterface)));
|
||||
mBlacklistedItems.AppendElement(nsCString(buf));
|
||||
}
|
||||
}
|
||||
@ -276,7 +288,8 @@ void
|
||||
nsHostRecord::ResetBlacklist()
|
||||
{
|
||||
// must call locked
|
||||
LOG(("Resetting blacklist for host [%s], host record [%p].\n", host, this));
|
||||
LOG(("Resetting blacklist for host [%s%s%s], host record [%p].\n",
|
||||
LOG_HOST(host, netInterface), this));
|
||||
mBlacklistedItems.Clear();
|
||||
}
|
||||
|
||||
@ -391,7 +404,8 @@ static PLDHashNumber
|
||||
HostDB_HashKey(PLDHashTable *table, const void *key)
|
||||
{
|
||||
const nsHostKey *hk = static_cast<const nsHostKey *>(key);
|
||||
return AddToHash(HashString(hk->host), RES_KEY_FLAGS(hk->flags), hk->af);
|
||||
return AddToHash(HashString(hk->host), RES_KEY_FLAGS(hk->flags), hk->af,
|
||||
HashString(hk->netInterface));
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -404,7 +418,8 @@ HostDB_MatchEntry(PLDHashTable *table,
|
||||
|
||||
return !strcmp(he->rec->host, hk->host) &&
|
||||
RES_KEY_FLAGS (he->rec->flags) == RES_KEY_FLAGS(hk->flags) &&
|
||||
he->rec->af == hk->af;
|
||||
he->rec->af == hk->af &&
|
||||
!strcmp(he->rec->netInterface, hk->netInterface);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -426,19 +441,23 @@ HostDB_ClearEntry(PLDHashTable *table,
|
||||
nsHostRecord *hr = he->rec;
|
||||
MOZ_ASSERT(hr, "nsHostDBEnt has null host record!");
|
||||
|
||||
LOG(("Clearing cache db entry for host [%s].\n", hr->host));
|
||||
LOG(("Clearing cache db entry for host [%s%s%s].\n",
|
||||
LOG_HOST(hr->host, hr->netInterface)));
|
||||
#if defined(DEBUG) && defined(PR_LOGGING)
|
||||
{
|
||||
MutexAutoLock lock(hr->addr_info_lock);
|
||||
if (!hr->addr_info) {
|
||||
LOG(("No address info for host [%s].\n", hr->host));
|
||||
LOG(("No address info for host [%s%s%s].\n",
|
||||
LOG_HOST(hr->host, hr->netInterface)));
|
||||
} else {
|
||||
if (!hr->mValidEnd.IsNull()) {
|
||||
TimeDuration diff = hr->mValidEnd - TimeStamp::NowLoRes();
|
||||
LOG(("Record for [%s] expires in %f seconds.\n", hr->host,
|
||||
LOG(("Record for host [%s%s%s] expires in %f seconds.\n",
|
||||
LOG_HOST(hr->host, hr->netInterface),
|
||||
diff.ToSeconds()));
|
||||
} else {
|
||||
LOG(("Record for [%s] not yet valid.\n", hr->host));
|
||||
LOG(("Record for host [%s%s%s] not yet valid.\n",
|
||||
LOG_HOST(hr->host, hr->netInterface)));
|
||||
}
|
||||
|
||||
NetAddrElement *addrElement = nullptr;
|
||||
@ -728,12 +747,14 @@ nsresult
|
||||
nsHostResolver::ResolveHost(const char *host,
|
||||
uint16_t flags,
|
||||
uint16_t af,
|
||||
const char *netInterface,
|
||||
nsResolveHostCallback *callback)
|
||||
{
|
||||
NS_ENSURE_TRUE(host && *host, NS_ERROR_UNEXPECTED);
|
||||
NS_ENSURE_TRUE(netInterface, NS_ERROR_UNEXPECTED);
|
||||
|
||||
LOG(("Resolving host [%s]%s.\n",
|
||||
host, flags & RES_BYPASS_CACHE ? " - bypassing cache" : ""));
|
||||
LOG(("Resolving host [%s%s%s]%s.\n", LOG_HOST(host, netInterface),
|
||||
flags & RES_BYPASS_CACHE ? " - bypassing cache" : ""));
|
||||
|
||||
// ensure that we are working with a valid hostname before proceeding. see
|
||||
// bug 304904 for details.
|
||||
@ -763,19 +784,21 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
// and return. otherwise, add ourselves as first pending
|
||||
// callback, and proceed to do the lookup.
|
||||
|
||||
nsHostKey key = { host, flags, af };
|
||||
nsHostKey key = { host, flags, af, netInterface };
|
||||
nsHostDBEnt *he = static_cast<nsHostDBEnt *>
|
||||
(PL_DHashTableAdd(&mDB, &key, fallible));
|
||||
|
||||
// if the record is null, the hash table OOM'd.
|
||||
if (!he) {
|
||||
LOG((" Out of memory: no cache entry for [%s].\n", host));
|
||||
LOG((" Out of memory: no cache entry for host [%s%s%s].\n",
|
||||
LOG_HOST(host, netInterface)));
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
// do we have a cached result that we can reuse?
|
||||
else if (!(flags & RES_BYPASS_CACHE) &&
|
||||
he->rec->HasUsableResult(TimeStamp::NowLoRes(), flags)) {
|
||||
LOG((" Using cached record for host [%s].\n", host));
|
||||
LOG((" Using cached record for host [%s%s%s].\n",
|
||||
LOG_HOST(host, netInterface)));
|
||||
// put reference to host record on stack...
|
||||
result = he->rec;
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2, METHOD_HIT);
|
||||
@ -786,7 +809,8 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
ConditionallyRefreshRecord(he->rec, host);
|
||||
|
||||
if (he->rec->negative) {
|
||||
LOG((" Negative cache entry for [%s].\n", host));
|
||||
LOG((" Negative cache entry for host [%s%s%s].\n",
|
||||
LOG_HOST(host, netInterface)));
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_NEGATIVE_HIT);
|
||||
status = NS_ERROR_UNKNOWN_HOST;
|
||||
@ -818,15 +842,17 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
!IsHighPriority(flags) &&
|
||||
!he->rec->resolving) {
|
||||
LOG((" Lookup queue full: dropping %s priority request for "
|
||||
"[%s].\n",
|
||||
IsMediumPriority(flags) ? "medium" : "low", host));
|
||||
"host [%s%s%s].\n",
|
||||
IsMediumPriority(flags) ? "medium" : "low",
|
||||
LOG_HOST(host, netInterface)));
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_OVERFLOW);
|
||||
// This is a lower priority request and we are swamped, so refuse it.
|
||||
rv = NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
|
||||
}
|
||||
else if (flags & RES_OFFLINE) {
|
||||
LOG((" Offline request for [%s]; ignoring.\n", host));
|
||||
LOG((" Offline request for host [%s%s%s]; ignoring.\n",
|
||||
LOG_HOST(host, netInterface)));
|
||||
rv = NS_ERROR_OFFLINE;
|
||||
}
|
||||
|
||||
@ -836,7 +862,8 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
if (!(flags & RES_BYPASS_CACHE) &&
|
||||
((af == PR_AF_INET) || (af == PR_AF_INET6))) {
|
||||
// First, search for an entry with AF_UNSPEC
|
||||
const nsHostKey unspecKey = { host, flags, PR_AF_UNSPEC };
|
||||
const nsHostKey unspecKey = { host, flags, PR_AF_UNSPEC,
|
||||
netInterface };
|
||||
nsHostDBEnt *unspecHe = static_cast<nsHostDBEnt *>
|
||||
(PL_DHashTableSearch(&mDB, &unspecKey));
|
||||
NS_ASSERTION(!unspecHe ||
|
||||
@ -849,8 +876,9 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
MOZ_ASSERT(unspecHe->rec->addr_info || unspecHe->rec->negative,
|
||||
"Entry should be resolved or negative.");
|
||||
|
||||
LOG((" Trying AF_UNSPEC entry for [%s] af: %s.\n",
|
||||
host, (af == PR_AF_INET) ? "AF_INET" : "AF_INET6"));
|
||||
LOG((" Trying AF_UNSPEC entry for host [%s%s%s] af: %s.\n",
|
||||
LOG_HOST(host, netInterface),
|
||||
(af == PR_AF_INET) ? "AF_INET" : "AF_INET6"));
|
||||
|
||||
he->rec->addr_info = nullptr;
|
||||
if (unspecHe->rec->negative) {
|
||||
@ -893,7 +921,8 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
// negative.
|
||||
else if (af == PR_AF_INET6) {
|
||||
LOG((" No AF_INET6 in AF_UNSPEC entry: "
|
||||
"[%s] unknown host", host));
|
||||
"host [%s%s%s] unknown host.",
|
||||
LOG_HOST(host, netInterface)));
|
||||
result = he->rec;
|
||||
he->rec->negative = true;
|
||||
status = NS_ERROR_UNKNOWN_HOST;
|
||||
@ -905,7 +934,9 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
// If no valid address was found in the cache or this is an
|
||||
// AF_UNSPEC request, then start a new lookup.
|
||||
if (!result) {
|
||||
LOG((" No usable address in cache for [%s]", host));
|
||||
LOG((" No usable address in cache for host [%s%s%s].",
|
||||
LOG_HOST(host, netInterface)));
|
||||
|
||||
// Add callback to the list of pending callbacks.
|
||||
PR_APPEND_LINK(callback, &he->rec->callbacks);
|
||||
he->rec->flags = flags;
|
||||
@ -916,15 +947,16 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
PR_REMOVE_AND_INIT_LINK(callback);
|
||||
}
|
||||
else {
|
||||
LOG((" DNS lookup for host [%s] blocking pending "
|
||||
"'getaddrinfo' query: callback [%p]",
|
||||
host, callback));
|
||||
LOG((" DNS lookup for host [%s%s%s] blocking "
|
||||
"pending 'getaddrinfo' query: callback [%p]",
|
||||
LOG_HOST(host, netInterface), callback));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG((" Host [%s] is being resolved. Appending callback [%p].",
|
||||
host, callback));
|
||||
LOG((" Host [%s%s%s] is being resolved. Appending callback "
|
||||
"[%p].", LOG_HOST(host, netInterface), callback));
|
||||
|
||||
PR_APPEND_LINK(callback, &he->rec->callbacks);
|
||||
if (he->rec->onQueue) {
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
@ -962,6 +994,7 @@ void
|
||||
nsHostResolver::DetachCallback(const char *host,
|
||||
uint16_t flags,
|
||||
uint16_t af,
|
||||
const char *netInterface,
|
||||
nsResolveHostCallback *callback,
|
||||
nsresult status)
|
||||
{
|
||||
@ -969,7 +1002,7 @@ nsHostResolver::DetachCallback(const char *host,
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
nsHostKey key = { host, flags, af };
|
||||
nsHostKey key = { host, flags, af, netInterface };
|
||||
nsHostDBEnt *he = static_cast<nsHostDBEnt *>
|
||||
(PL_DHashTableSearch(&mDB, &key));
|
||||
if (he) {
|
||||
@ -1020,8 +1053,10 @@ nsHostResolver::ConditionallyCreateThread(nsHostRecord *rec)
|
||||
}
|
||||
}
|
||||
#if defined(PR_LOGGING)
|
||||
else
|
||||
LOG((" Unable to find a thread for looking up host [%s].\n", rec->host));
|
||||
else {
|
||||
LOG((" Unable to find a thread for looking up host [%s%s%s].\n",
|
||||
LOG_HOST(rec->host, rec->netInterface)));
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1185,7 +1220,8 @@ nsHostResolver::PrepareRecordExpiration(nsHostRecord* rec) const
|
||||
if (!rec->addr_info) {
|
||||
rec->SetExpiration(TimeStamp::NowLoRes(),
|
||||
NEGATIVE_RECORD_LIFETIME, 0);
|
||||
LOG(("Caching [%s] negative record for %u seconds.\n", rec->host,
|
||||
LOG(("Caching host [%s%s%s] negative record for %u seconds.\n",
|
||||
LOG_HOST(rec->host, rec->netInterface),
|
||||
NEGATIVE_RECORD_LIFETIME));
|
||||
return;
|
||||
}
|
||||
@ -1205,8 +1241,8 @@ nsHostResolver::PrepareRecordExpiration(nsHostRecord* rec) const
|
||||
#endif
|
||||
|
||||
rec->SetExpiration(TimeStamp::NowLoRes(), lifetime, grace);
|
||||
LOG(("Caching [%s] record for %u seconds (grace %d).",
|
||||
rec->host, lifetime, grace));
|
||||
LOG(("Caching host [%s%s%s] record for %u seconds (grace %d).",
|
||||
LOG_HOST(rec->host, rec->netInterface), lifetime, grace));
|
||||
}
|
||||
|
||||
//
|
||||
@ -1277,7 +1313,8 @@ nsHostResolver::OnLookupComplete(nsHostRecord* rec, nsresult status, AddrInfo* r
|
||||
}
|
||||
#if TTL_AVAILABLE
|
||||
if (!rec->mGetTtl && !rec->resolving && sGetTtlEnabled) {
|
||||
LOG(("Issuing second async lookup for TTL for %s.", rec->host));
|
||||
LOG(("Issuing second async lookup for TTL for host [%s%s%s].",
|
||||
LOG_HOST(rec->host, rec->netInterface)));
|
||||
rec->flags =
|
||||
(rec->flags & ~RES_PRIORITY_MEDIUM) | RES_PRIORITY_LOW;
|
||||
DebugOnly<nsresult> rv = IssueLookup(rec);
|
||||
@ -1310,6 +1347,7 @@ void
|
||||
nsHostResolver::CancelAsyncRequest(const char *host,
|
||||
uint16_t flags,
|
||||
uint16_t af,
|
||||
const char *netInterface,
|
||||
nsIDNSListener *aListener,
|
||||
nsresult status)
|
||||
|
||||
@ -1317,7 +1355,7 @@ nsHostResolver::CancelAsyncRequest(const char *host,
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
// Lookup the host record associated with host, flags & address family
|
||||
nsHostKey key = { host, flags, af };
|
||||
nsHostKey key = { host, flags, af, netInterface };
|
||||
nsHostDBEnt *he = static_cast<nsHostDBEnt *>
|
||||
(PL_DHashTableSearch(&mDB, &key));
|
||||
if (he) {
|
||||
@ -1391,8 +1429,8 @@ nsHostResolver::ThreadFunc(void *arg)
|
||||
AddrInfo *ai = nullptr;
|
||||
|
||||
while (rec || resolver->GetHostToLookup(&rec)) {
|
||||
LOG(("DNS lookup thread - Calling getaddrinfo for host [%s].\n",
|
||||
rec->host));
|
||||
LOG(("DNS lookup thread - Calling getaddrinfo for host [%s%s%s].\n",
|
||||
LOG_HOST(rec->host, rec->netInterface)));
|
||||
|
||||
TimeStamp startTime = TimeStamp::Now();
|
||||
MOZ_EVENT_TRACER_EXEC(rec, "net::dns::resolve");
|
||||
@ -1407,10 +1445,12 @@ nsHostResolver::ThreadFunc(void *arg)
|
||||
// because PR_GetAddrInfoByName doesn't support PR_AF_INET6.
|
||||
bool disableIPv4 = rec->af == PR_AF_INET6;
|
||||
uint16_t af = disableIPv4 ? PR_AF_UNSPEC : rec->af;
|
||||
nsresult status = GetAddrInfo(rec->host, af, rec->flags, &ai, getTtl);
|
||||
nsresult status = GetAddrInfo(rec->host, af, rec->flags, rec->netInterface,
|
||||
&ai, getTtl);
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
if (NS_FAILED(status) && rs.Reset()) {
|
||||
status = GetAddrInfo(rec->host, af, rec->flags, &ai, getTtl);
|
||||
status = GetAddrInfo(rec->host, af, rec->flags, rec->netInterface, &ai,
|
||||
getTtl);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1435,12 +1475,14 @@ nsHostResolver::ThreadFunc(void *arg)
|
||||
}
|
||||
|
||||
// OnLookupComplete may release "rec", long before we lose it.
|
||||
LOG(("DNS lookup thread - lookup completed for host [%s]: %s.\n",
|
||||
rec->host, ai ? "success" : "failure: unknown host"));
|
||||
LOG(("DNS lookup thread - lookup completed for host [%s%s%s]: %s.\n",
|
||||
LOG_HOST(rec->host, rec->netInterface),
|
||||
ai ? "success" : "failure: unknown host"));
|
||||
|
||||
if (LOOKUP_RESOLVEAGAIN == resolver->OnLookupComplete(rec, status, ai)) {
|
||||
// leave 'rec' assigned and loop to make a renewed host resolve
|
||||
LOG(("DNS lookup thread - Re-resolving host [%s].\n",
|
||||
rec->host));
|
||||
LOG(("DNS lookup thread - Re-resolving host [%s%s%s].\n",
|
||||
LOG_HOST(rec->host, rec->netInterface)));
|
||||
} else {
|
||||
rec = nullptr;
|
||||
}
|
||||
@ -1489,6 +1531,7 @@ CacheEntryEnumerator(PLDHashTable *table, PLDHashEntryHdr *entry,
|
||||
DNSCacheEntries info;
|
||||
info.hostname = rec->host;
|
||||
info.family = rec->af;
|
||||
info.netInterface = rec->netInterface;
|
||||
info.expiration =
|
||||
(int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds();
|
||||
if (info.expiration <= 0) {
|
||||
|
@ -37,6 +37,7 @@ struct nsHostKey
|
||||
const char *host;
|
||||
uint16_t flags;
|
||||
uint16_t af;
|
||||
const char *netInterface;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -241,6 +242,7 @@ public:
|
||||
nsresult ResolveHost(const char *hostname,
|
||||
uint16_t flags,
|
||||
uint16_t af,
|
||||
const char *netInterface,
|
||||
nsResolveHostCallback *callback);
|
||||
|
||||
/**
|
||||
@ -252,6 +254,7 @@ public:
|
||||
void DetachCallback(const char *hostname,
|
||||
uint16_t flags,
|
||||
uint16_t af,
|
||||
const char *netInterface,
|
||||
nsResolveHostCallback *callback,
|
||||
nsresult status);
|
||||
|
||||
@ -265,6 +268,7 @@ public:
|
||||
void CancelAsyncRequest(const char *host,
|
||||
uint16_t flags,
|
||||
uint16_t af,
|
||||
const char *netInterface,
|
||||
nsIDNSListener *aListener,
|
||||
nsresult status);
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ namespace mozilla { namespace net {
|
||||
/**
|
||||
* nsIDNSService
|
||||
*/
|
||||
[scriptable, uuid(f1971942-19db-44bf-81e8-d15df220a39f)]
|
||||
[scriptable, uuid(de5642c6-61fc-4fcf-9a47-03226b0d4e21)]
|
||||
interface nsIDNSService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -66,7 +66,7 @@ interface nsIDNSService : nsISupports
|
||||
in unsigned long aFlags,
|
||||
in nsIDNSListener aListener,
|
||||
in nsresult aReason);
|
||||
|
||||
|
||||
/**
|
||||
* called to synchronously resolve a hostname. warning this method may
|
||||
* block the calling thread for a long period of time. it is extremely
|
||||
@ -83,6 +83,31 @@ interface nsIDNSService : nsISupports
|
||||
nsIDNSRecord resolve(in AUTF8String aHostName,
|
||||
in unsigned long aFlags);
|
||||
|
||||
/**
|
||||
* kicks off an asynchronous host lookup.
|
||||
*
|
||||
* This function is identical to asyncResolve except an additional
|
||||
* parameter aNetwortInterface. If parameter aNetworkInterface is an empty
|
||||
* string function will return the same result as asyncResolve.
|
||||
* Setting aNetworkInterface value make only sense for gonk,because it
|
||||
* an per networking interface query is possible.
|
||||
*/
|
||||
nsICancelable asyncResolveExtended(in AUTF8String aHostName,
|
||||
in unsigned long aFlags,
|
||||
in AUTF8String aNetworkInterface,
|
||||
in nsIDNSListener aListener,
|
||||
in nsIEventTarget aListenerTarget);
|
||||
|
||||
/**
|
||||
* Attempts to cancel a previously requested async DNS lookup
|
||||
* This is an extended versin with a additional parameter aNetworkInterface
|
||||
*/
|
||||
void cancelAsyncResolveExtended(in AUTF8String aHostName,
|
||||
in unsigned long aFlags,
|
||||
in AUTF8String aNetworkInterface,
|
||||
in nsIDNSListener aListener,
|
||||
in nsresult aReason);
|
||||
|
||||
/**
|
||||
* The method takes a pointer to an nsTArray
|
||||
* and fills it with cache entry data
|
||||
|
@ -254,7 +254,8 @@ NeckoChild::DeallocPUDPSocketChild(PUDPSocketChild* child)
|
||||
|
||||
PDNSRequestChild*
|
||||
NeckoChild::AllocPDNSRequestChild(const nsCString& aHost,
|
||||
const uint32_t& aFlags)
|
||||
const uint32_t& aFlags,
|
||||
const nsCString& aNetworkInterface)
|
||||
{
|
||||
// We don't allocate here: instead we always use IPDL constructor that takes
|
||||
// an existing object
|
||||
|
@ -54,7 +54,8 @@ protected:
|
||||
virtual PUDPSocketChild* AllocPUDPSocketChild(const nsCString& aFilter) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPUDPSocketChild(PUDPSocketChild*) MOZ_OVERRIDE;
|
||||
virtual PDNSRequestChild* AllocPDNSRequestChild(const nsCString& aHost,
|
||||
const uint32_t& aFlags) MOZ_OVERRIDE;
|
||||
const uint32_t& aFlags,
|
||||
const nsCString& aNetworkInterface) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPDNSRequestChild(PDNSRequestChild*) MOZ_OVERRIDE;
|
||||
virtual PRemoteOpenFileChild*
|
||||
AllocPRemoteOpenFileChild(const SerializedLoadContext& aSerialized,
|
||||
|
@ -479,7 +479,8 @@ NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor)
|
||||
|
||||
PDNSRequestParent*
|
||||
NeckoParent::AllocPDNSRequestParent(const nsCString& aHost,
|
||||
const uint32_t& aFlags)
|
||||
const uint32_t& aFlags,
|
||||
const nsCString& aNetworkInterface)
|
||||
{
|
||||
DNSRequestParent *p = new DNSRequestParent();
|
||||
p->AddRef();
|
||||
@ -489,9 +490,11 @@ NeckoParent::AllocPDNSRequestParent(const nsCString& aHost,
|
||||
bool
|
||||
NeckoParent::RecvPDNSRequestConstructor(PDNSRequestParent* aActor,
|
||||
const nsCString& aHost,
|
||||
const uint32_t& aFlags)
|
||||
const uint32_t& aFlags,
|
||||
const nsCString& aNetworkInterface)
|
||||
{
|
||||
static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(aHost, aFlags);
|
||||
static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(aHost, aFlags,
|
||||
aNetworkInterface);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -153,10 +153,12 @@ protected:
|
||||
virtual bool RecvPUDPSocketConstructor(PUDPSocketParent*, const nsCString& aFilter) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPUDPSocketParent(PUDPSocketParent*) MOZ_OVERRIDE;
|
||||
virtual PDNSRequestParent* AllocPDNSRequestParent(const nsCString& aHost,
|
||||
const uint32_t& aFlags) MOZ_OVERRIDE;
|
||||
const uint32_t& aFlags,
|
||||
const nsCString& aNetworkInterface) MOZ_OVERRIDE;
|
||||
virtual bool RecvPDNSRequestConstructor(PDNSRequestParent* actor,
|
||||
const nsCString& hostName,
|
||||
const uint32_t& flags) MOZ_OVERRIDE;
|
||||
const uint32_t& flags,
|
||||
const nsCString& aNetworkInterface) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPDNSRequestParent(PDNSRequestParent*) MOZ_OVERRIDE;
|
||||
virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
|
||||
const uint16_t& flags) MOZ_OVERRIDE;
|
||||
|
@ -67,7 +67,7 @@ parent:
|
||||
PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType);
|
||||
PUDPSocket(nsCString filter);
|
||||
|
||||
PDNSRequest(nsCString hostName, uint32_t flags);
|
||||
PDNSRequest(nsCString hostName, uint32_t flags, nsCString networkInterface);
|
||||
|
||||
PRemoteOpenFile(SerializedLoadContext loadContext,
|
||||
URIParams fileuri,
|
||||
|
79
netwerk/test/unit/test_dns_per_interface.js
Normal file
79
netwerk/test/unit/test_dns_per_interface.js
Normal file
@ -0,0 +1,79 @@
|
||||
var dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService);
|
||||
|
||||
// This test checks DNSService host resolver when a network interface is supplied
|
||||
// as well. In the test 3 request are sent: two with a network interface set
|
||||
// and one without a network interface.
|
||||
// All requests have the same host to be resolved and the same flags.
|
||||
// One of the request with the network interface will be canceled.
|
||||
// The request with and without a network interface should not be mixed during
|
||||
// the requests lifetime.
|
||||
|
||||
var netInterface1 = "interface1";
|
||||
var netInterface2 = "interface2";
|
||||
|
||||
// We are not using localhost because on e10s a host resolve callback is almost
|
||||
// always faster than a cancel request, therefore cancel operation would not be
|
||||
// tested.
|
||||
var hostname = "thisshouldnotexist.mozilla.com";
|
||||
|
||||
// 3 requests.
|
||||
var requestWithInterfaceCanceled;
|
||||
var requestWithoutInterfaceNotCanceled;
|
||||
var requestWithInterfaceNotCanceled;
|
||||
|
||||
var listener = {
|
||||
onLookupComplete: function(inRequest, inRecord, inStatus) {
|
||||
// Two requests should be resolved and one request should be canceled.
|
||||
// Since cancalation of a request is racy we will check only for not
|
||||
// canceled request - they should not be canceled.
|
||||
if ((inRequest == requestWithoutInterfaceNotCanceled) ||
|
||||
(inRequest == requestWithInterfaceNotCanceled)) {
|
||||
// This request should not be canceled.
|
||||
do_check_neq(inStatus, Cr.NS_ERROR_ABORT);
|
||||
|
||||
do_test_finished();
|
||||
} else if (inRequest == requestWithInterfaceCanceled) {
|
||||
// We do not check the outcome for this one because it is racy -
|
||||
// whether the request cancelation is faster than resolving the request.
|
||||
do_test_finished();
|
||||
}
|
||||
},
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Ci.nsIDNSListener) ||
|
||||
aIID.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
var threadManager = Cc["@mozilla.org/thread-manager;1"]
|
||||
.getService(Ci.nsIThreadManager);
|
||||
var mainThread = threadManager.currentThread;
|
||||
|
||||
var flags = Ci.nsIDNSService.RESOLVE_BYPASS_CACHE;
|
||||
|
||||
// This one will be canceled.
|
||||
requestWithInterfaceCanceled = dns.asyncResolveExtended(hostname, flags,
|
||||
netInterface1,
|
||||
listener,
|
||||
mainThread);
|
||||
requestWithInterfaceCanceled.cancel(Cr.NS_ERROR_ABORT);
|
||||
|
||||
// This one will not be canceled. This is the request without a network
|
||||
// interface.
|
||||
requestWithoutInterfaceNotCanceled = dns.asyncResolve(hostname, flags,
|
||||
listener, mainThread);
|
||||
|
||||
// This one will not be canceled.
|
||||
requestWithInterfaceNotCanceled = dns.asyncResolveExtended(hostname, flags,
|
||||
netInterface2,
|
||||
listener,
|
||||
mainThread);
|
||||
// We wait for notifications for the requests.
|
||||
// For each request onLookupComplete will be called.
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
}
|
@ -173,6 +173,7 @@ skip-if = bits != 32
|
||||
[test_cookiejars.js]
|
||||
[test_cookiejars_safebrowsing.js]
|
||||
[test_dns_cancel.js]
|
||||
[test_dns_per_interface.js]
|
||||
[test_data_protocol.js]
|
||||
[test_dns_service.js]
|
||||
[test_dns_localredirect.js]
|
||||
|
7
netwerk/test/unit_ipc/test_dns_per_interface_wrap.js
Normal file
7
netwerk/test/unit_ipc/test_dns_per_interface_wrap.js
Normal file
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_dns_per_interface.js");
|
||||
}
|
@ -12,6 +12,7 @@ support-files = child_app_offline.js
|
||||
[test_cookie_header_wrap.js]
|
||||
[test_cookiejars_wrap.js]
|
||||
[test_dns_cancel_wrap.js]
|
||||
[test_dns_per_interface_wrap.js]
|
||||
[test_dns_service_wrap.js]
|
||||
[test_duplicate_headers_wrap.js]
|
||||
[test_event_sink_wrap.js]
|
||||
|
Loading…
Reference in New Issue
Block a user