зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 6 changesets (bug 1623126) for build bustage in include/mozilla/net/HTTPSSVC.h. CLOSED TREE
Backed out changeset a2138b587838 (bug 1623126) Backed out changeset d007557a3278 (bug 1623126) Backed out changeset 04f7ec5742c5 (bug 1623126) Backed out changeset 48466d966ef0 (bug 1623126) Backed out changeset 80cfd249692b (bug 1623126) Backed out changeset d49b0ed494f7 (bug 1623126)
This commit is contained in:
Родитель
9d800df7de
Коммит
8278ad20d7
|
@ -12,6 +12,12 @@ using namespace mozilla::net;
|
|||
|
||||
NS_IMPL_ISUPPORTS(nsNetAddr, nsINetAddr)
|
||||
|
||||
/* Makes a copy of |addr| */
|
||||
nsNetAddr::nsNetAddr(NetAddr* addr) {
|
||||
NS_ASSERTION(addr, "null addr");
|
||||
mAddr = *addr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsNetAddr::GetFamily(uint16_t* aFamily) {
|
||||
switch (mAddr.raw.family) {
|
||||
case AF_INET:
|
||||
|
|
|
@ -18,7 +18,7 @@ class nsNetAddr final : public nsINetAddr {
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETADDR
|
||||
|
||||
explicit nsNetAddr(const mozilla::net::NetAddr* addr) : mAddr(*addr) {}
|
||||
explicit nsNetAddr(mozilla::net::NetAddr* addr);
|
||||
|
||||
private:
|
||||
mozilla::net::NetAddr mAddr;
|
||||
|
|
|
@ -2971,7 +2971,7 @@ nsSocketTransport::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
|
|||
|
||||
if (request == mDNSTxtRequest) {
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
nsCOMPtr<nsIDNSTXTRecord> txtResponse = do_QueryInterface(rec);
|
||||
nsCOMPtr<nsIDNSByTypeRecord> txtResponse = do_QueryInterface(rec);
|
||||
txtResponse->GetRecordsAsOneString(mDNSRecordTxt);
|
||||
mDNSRecordTxt.Trim(" ");
|
||||
}
|
||||
|
|
|
@ -1,221 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DNSByTypeRecord_h__
|
||||
#define DNSByTypeRecord_h__
|
||||
|
||||
#include "mozilla/net/HTTPSSVC.h"
|
||||
#include "mozilla/ipc/IPDLParamTraits.h"
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/net/NeckoMessageUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// The types of nsIDNSByTypeRecord: Nothing, TXT, HTTPSSVC
|
||||
using TypeRecordEmpty = Nothing;
|
||||
using TypeRecordTxt = nsTArray<nsCString>;
|
||||
using TypeRecordHTTPSSVC = nsTArray<SVCB>;
|
||||
|
||||
// This variant reflects the multiple types of data a nsIDNSByTypeRecord
|
||||
// can hold.
|
||||
using TypeRecordResultType =
|
||||
Variant<TypeRecordEmpty, TypeRecordTxt, TypeRecordHTTPSSVC>;
|
||||
|
||||
// TypeRecordResultType is a variant, but since it doesn't have a default
|
||||
// constructor it's not a type we can pass directly over IPC.
|
||||
struct IPCTypeRecord {
|
||||
bool operator==(const IPCTypeRecord& aOther) const {
|
||||
return mData == aOther.mData;
|
||||
}
|
||||
IPCTypeRecord() : mData(Nothing{}) {}
|
||||
TypeRecordResultType mData;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::IPCTypeRecord> {
|
||||
typedef mozilla::net::IPCTypeRecord paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mData);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mData)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::Nothing> {
|
||||
typedef mozilla::Nothing paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
bool isSome = false;
|
||||
WriteIPDLParam(aMsg, aActor, isSome);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
bool isSome;
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &isSome)) {
|
||||
return false;
|
||||
}
|
||||
*aResult = Nothing();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SVCB> {
|
||||
typedef mozilla::net::SVCB paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mSvcFieldPriority);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mSvcDomainName);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mSvcFieldValue);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSvcFieldPriority)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSvcDomainName)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSvcFieldValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SvcParamAlpn> {
|
||||
typedef mozilla::net::SvcParamAlpn paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mValue);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SvcParamNoDefaultAlpn> {
|
||||
typedef mozilla::net::SvcParamNoDefaultAlpn paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SvcParamPort> {
|
||||
typedef mozilla::net::SvcParamPort paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mValue);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SvcParamIpv4Hint> {
|
||||
typedef mozilla::net::SvcParamIpv4Hint paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mValue);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SvcParamEsniConfig> {
|
||||
typedef mozilla::net::SvcParamEsniConfig paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mValue);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SvcParamIpv6Hint> {
|
||||
typedef mozilla::net::SvcParamIpv6Hint paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mValue);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::net::SvcFieldValue> {
|
||||
typedef mozilla::net::SvcFieldValue paramType;
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mValue);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DNSByTypeRecord_h__
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/net/ChildDNSService.h"
|
||||
#include "mozilla/net/DNSByTypeRecord.h"
|
||||
#include "mozilla/net/DNSRequestChild.h"
|
||||
#include "mozilla/net/DNSRequestParent.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
|
@ -165,83 +164,38 @@ ChildDNSRecord::ReportUnusable(uint16_t aPort) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class ChildDNSByTypeRecord : public nsIDNSByTypeRecord,
|
||||
public nsIDNSTXTRecord,
|
||||
public nsIDNSHTTPSSVCRecord {
|
||||
class ChildDNSByTypeRecord : public nsIDNSByTypeRecord {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_FORWARD_SAFE_NSIDNSRECORD(((nsIDNSRecord*)nullptr))
|
||||
NS_DECL_NSIDNSBYTYPERECORD
|
||||
NS_DECL_NSIDNSTXTRECORD
|
||||
NS_DECL_NSIDNSHTTPSSVCRECORD
|
||||
|
||||
explicit ChildDNSByTypeRecord(const TypeRecordResultType& reply);
|
||||
explicit ChildDNSByTypeRecord(const nsTArray<nsCString>& reply);
|
||||
|
||||
private:
|
||||
virtual ~ChildDNSByTypeRecord() = default;
|
||||
|
||||
TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
|
||||
nsTArray<nsCString> mRecords;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ChildDNSByTypeRecord, nsIDNSByTypeRecord, nsIDNSRecord,
|
||||
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
|
||||
NS_IMPL_ISUPPORTS(ChildDNSByTypeRecord, nsIDNSByTypeRecord, nsIDNSRecord)
|
||||
|
||||
ChildDNSByTypeRecord::ChildDNSByTypeRecord(const TypeRecordResultType& reply) {
|
||||
mResults = reply;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSByTypeRecord::GetType(uint32_t* aType) {
|
||||
*aType = mResults.match(
|
||||
[](TypeRecordEmpty&) {
|
||||
MOZ_ASSERT(false, "This should never be the case");
|
||||
return nsIDNSService::RESOLVE_TYPE_DEFAULT;
|
||||
},
|
||||
[](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
|
||||
[](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
|
||||
return NS_OK;
|
||||
ChildDNSByTypeRecord::ChildDNSByTypeRecord(const nsTArray<nsCString>& reply) {
|
||||
mRecords = reply;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSByTypeRecord::GetRecords(nsTArray<nsCString>& aRecords) {
|
||||
if (!mResults.is<TypeRecordTxt>()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
aRecords = mResults.as<nsTArray<nsCString>>();
|
||||
aRecords = mRecords;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSByTypeRecord::GetRecordsAsOneString(nsACString& aRecords) {
|
||||
// deep copy
|
||||
if (!mResults.is<TypeRecordTxt>()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
for (uint32_t i = 0; i < mRecords.Length(); i++) {
|
||||
aRecords.Append(mRecords[i]);
|
||||
}
|
||||
auto& results = mResults.as<nsTArray<nsCString>>();
|
||||
for (uint32_t i = 0; i < results.Length(); i++) {
|
||||
aRecords.Append(results[i]);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSByTypeRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
|
||||
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
||||
|
||||
for (const SVCB& r : results) {
|
||||
RefPtr<nsISVCBRecord> rec = new SVCBRecord(r);
|
||||
aRecords.AppendElement(rec);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChildDNSByTypeRecord::GetResults(mozilla::net::TypeRecordResultType* aResults) {
|
||||
*aResults = mResults;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -374,9 +328,9 @@ bool DNSRequestSender::OnRecvLookupCompleted(const DNSRequestResponse& reply) {
|
|||
mResultStatus = reply.get_nsresult();
|
||||
break;
|
||||
}
|
||||
case DNSRequestResponse::TIPCTypeRecord: {
|
||||
case DNSRequestResponse::TArrayOfnsCString: {
|
||||
MOZ_ASSERT(mType != nsIDNSService::RESOLVE_TYPE_DEFAULT);
|
||||
mResultRecord = new ChildDNSByTypeRecord(reply.get_IPCTypeRecord().mData);
|
||||
mResultRecord = new ChildDNSByTypeRecord(reply.get_ArrayOfnsCString());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -105,11 +105,11 @@ DNSRequestHandler::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
|
|||
if (NS_SUCCEEDED(status)) {
|
||||
MOZ_ASSERT(rec);
|
||||
|
||||
nsCOMPtr<nsIDNSByTypeRecord> byTypeRec = do_QueryInterface(rec);
|
||||
if (byTypeRec) {
|
||||
IPCTypeRecord result;
|
||||
byTypeRec->GetResults(&result.mData);
|
||||
SendLookupCompletedHelper(mIPCActor, DNSRequestResponse(result));
|
||||
nsCOMPtr<nsIDNSByTypeRecord> txtRec = do_QueryInterface(rec);
|
||||
if (txtRec) {
|
||||
nsTArray<nsCString> rec;
|
||||
txtRec->GetRecords(rec);
|
||||
SendLookupCompletedHelper(mIPCActor, DNSRequestResponse(rec));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ DNSRequestHandler::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
|
|||
}
|
||||
|
||||
// Get IP addresses for hostname (use port 80 as dummy value for NetAddr)
|
||||
nsTArray<NetAddr> array;
|
||||
NetAddrArray array;
|
||||
NetAddr addr;
|
||||
while (NS_SUCCEEDED(rec->GetNextAddr(80, &addr))) {
|
||||
array.AppendElement(addr);
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "HTTPSSVC.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include "nsNetAddr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS(SVCBRecord, nsISVCBRecord)
|
||||
|
||||
class SvcParam : public nsISVCParam,
|
||||
public nsISVCParamAlpn,
|
||||
public nsISVCParamNoDefaultAlpn,
|
||||
public nsISVCParamPort,
|
||||
public nsISVCParamIPv4Hint,
|
||||
public nsISVCParamEsniConfig,
|
||||
public nsISVCParamIPv6Hint {
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSISVCPARAM
|
||||
NS_DECL_NSISVCPARAMALPN
|
||||
NS_DECL_NSISVCPARAMNODEFAULTALPN
|
||||
NS_DECL_NSISVCPARAMPORT
|
||||
NS_DECL_NSISVCPARAMIPV4HINT
|
||||
NS_DECL_NSISVCPARAMESNICONFIG
|
||||
NS_DECL_NSISVCPARAMIPV6HINT
|
||||
public:
|
||||
SvcParam(const SvcParamType& value) : mValue(value){};
|
||||
|
||||
private:
|
||||
virtual ~SvcParam() = default;
|
||||
SvcParamType mValue;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(SvcParam)
|
||||
NS_IMPL_RELEASE(SvcParam)
|
||||
NS_INTERFACE_MAP_BEGIN(SvcParam)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISVCParam)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVCParam)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISVCParamAlpn, mValue.is<SvcParamAlpn>())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISVCParamNoDefaultAlpn,
|
||||
mValue.is<SvcParamNoDefaultAlpn>())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISVCParamPort, mValue.is<SvcParamPort>())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISVCParamIPv4Hint,
|
||||
mValue.is<SvcParamIpv4Hint>())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISVCParamEsniConfig,
|
||||
mValue.is<SvcParamEsniConfig>())
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISVCParamIPv6Hint,
|
||||
mValue.is<SvcParamIpv6Hint>())
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMETHODIMP
|
||||
SvcParam::GetType(uint16_t* aType) {
|
||||
*aType = mValue.match(
|
||||
[](Nothing&) { return SvcParamKeyNone; },
|
||||
[](SvcParamAlpn&) { return SvcParamKeyAlpn; },
|
||||
[](SvcParamNoDefaultAlpn&) { return SvcParamKeyNoDefaultAlpn; },
|
||||
[](SvcParamPort&) { return SvcParamKeyPort; },
|
||||
[](SvcParamIpv4Hint&) { return SvcParamKeyIpv4Hint; },
|
||||
[](SvcParamEsniConfig&) { return SvcParamKeyEsniConfig; },
|
||||
[](SvcParamIpv6Hint&) { return SvcParamKeyIpv6Hint; });
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SvcParam::GetAlpn(nsACString& aAlpn) {
|
||||
if (!mValue.is<SvcParamAlpn>()) {
|
||||
MOZ_ASSERT(false, "Unexpected type for variant");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
aAlpn = mValue.as<SvcParamAlpn>().mValue;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SvcParam::GetPort(uint16_t* aPort) {
|
||||
if (!mValue.is<SvcParamPort>()) {
|
||||
MOZ_ASSERT(false, "Unexpected type for variant");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
*aPort = mValue.as<SvcParamPort>().mValue;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SvcParam::GetEsniConfig(nsACString& aEsniConfig) {
|
||||
if (!mValue.is<SvcParamEsniConfig>()) {
|
||||
MOZ_ASSERT(false, "Unexpected type for variant");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
aEsniConfig = mValue.as<SvcParamEsniConfig>().mValue;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SvcParam::GetIpv4Hint(nsTArray<RefPtr<nsINetAddr>>& aIpv4Hint) {
|
||||
if (!mValue.is<SvcParamIpv4Hint>()) {
|
||||
MOZ_ASSERT(false, "Unexpected type for variant");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
const auto& results = mValue.as<SvcParamIpv4Hint>().mValue;
|
||||
for (const auto& ip : results) {
|
||||
if (ip.raw.family != AF_INET) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
RefPtr<nsINetAddr> hint = new nsNetAddr(&ip);
|
||||
aIpv4Hint.AppendElement(hint);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SvcParam::GetIpv6Hint(nsTArray<RefPtr<nsINetAddr>>& aIpv6Hint) {
|
||||
if (!mValue.is<SvcParamIpv6Hint>()) {
|
||||
MOZ_ASSERT(false, "Unexpected type for variant");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
const auto& results = mValue.as<SvcParamIpv6Hint>().mValue;
|
||||
for (const auto& ip : results) {
|
||||
if (ip.raw.family != AF_INET6) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
RefPtr<nsINetAddr> hint = new nsNetAddr(&ip);
|
||||
aIpv6Hint.AppendElement(hint);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP SVCBRecord::GetPriority(uint16_t* aPriority) {
|
||||
*aPriority = mData.mSvcFieldPriority;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP SVCBRecord::GetName(nsACString& aName) {
|
||||
aName = mData.mSvcDomainName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP SVCBRecord::GetValues(nsTArray<RefPtr<nsISVCParam>>& aValues) {
|
||||
for (const auto& v : mData.mSvcFieldValue) {
|
||||
RefPtr<nsISVCParam> param = new SvcParam(v.mValue);
|
||||
aValues.AppendElement(param);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -1,104 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef HTTPSSVC_h__
|
||||
#define HTTPSSVC_h__
|
||||
|
||||
#include "nsIDNSByTypeRecord.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include "mozilla/Variant.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
enum SvcParamKey : uint16_t {
|
||||
SvcParamKeyNone = 0,
|
||||
SvcParamKeyAlpn = 1,
|
||||
SvcParamKeyNoDefaultAlpn = 2,
|
||||
SvcParamKeyPort = 3,
|
||||
SvcParamKeyIpv4Hint = 4,
|
||||
SvcParamKeyEsniConfig = 5,
|
||||
SvcParamKeyIpv6Hint = 6,
|
||||
|
||||
SvcParamKeyLast = SvcParamKeyIpv6Hint
|
||||
};
|
||||
|
||||
struct SvcParamAlpn {
|
||||
bool operator==(const SvcParamAlpn& aOther) const {
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
nsCString mValue;
|
||||
};
|
||||
|
||||
struct SvcParamNoDefaultAlpn {
|
||||
bool operator==(const SvcParamNoDefaultAlpn& aOther) const { return true; }
|
||||
};
|
||||
|
||||
struct SvcParamPort {
|
||||
bool operator==(const SvcParamPort& aOther) const {
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
uint16_t mValue;
|
||||
};
|
||||
|
||||
struct SvcParamIpv4Hint {
|
||||
bool operator==(const SvcParamIpv4Hint& aOther) const {
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
nsTArray<mozilla::net::NetAddr> mValue;
|
||||
};
|
||||
|
||||
struct SvcParamEsniConfig {
|
||||
bool operator==(const SvcParamEsniConfig& aOther) const {
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
nsCString mValue;
|
||||
};
|
||||
|
||||
struct SvcParamIpv6Hint {
|
||||
bool operator==(const SvcParamIpv6Hint& aOther) const {
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
nsTArray<mozilla::net::NetAddr> mValue;
|
||||
};
|
||||
|
||||
using SvcParamType =
|
||||
mozilla::Variant<Nothing, SvcParamAlpn, SvcParamNoDefaultAlpn, SvcParamPort,
|
||||
SvcParamIpv4Hint, SvcParamEsniConfig, SvcParamIpv6Hint>;
|
||||
|
||||
struct SvcFieldValue {
|
||||
bool operator==(const SvcFieldValue& aOther) const {
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
SvcFieldValue() : mValue(AsVariant(Nothing{})) {}
|
||||
SvcParamType mValue;
|
||||
};
|
||||
|
||||
struct SVCB {
|
||||
bool operator==(const SVCB& aOther) const {
|
||||
return mSvcFieldPriority == aOther.mSvcFieldPriority &&
|
||||
mSvcDomainName == aOther.mSvcDomainName &&
|
||||
mSvcFieldValue == aOther.mSvcFieldValue;
|
||||
}
|
||||
uint16_t mSvcFieldPriority = SvcParamKeyNone;
|
||||
nsCString mSvcDomainName;
|
||||
nsTArray<SvcFieldValue> mSvcFieldValue;
|
||||
};
|
||||
|
||||
class SVCBRecord : public nsISVCBRecord {
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSISVCBRECORD
|
||||
public:
|
||||
SVCBRecord(const SVCB& data) : mData(data) {}
|
||||
|
||||
private:
|
||||
virtual ~SVCBRecord() = default;
|
||||
SVCB mData;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // HTTPSSVC_h__
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=c: */
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef PDNSParams_h
|
||||
#define PDNSParams_h
|
||||
|
||||
#include "DNS.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// Need to define typedef in .h file--can't seem to in ipdl.h file?
|
||||
typedef nsTArray<NetAddr> NetAddrArray;
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // PDNSParams_h
|
|
@ -5,9 +5,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using NetAddr from "mozilla/net/DNS.h";
|
||||
using mozilla::net::IPCTypeRecord from "mozilla/net/DNSByTypeRecord.h";
|
||||
|
||||
using NetAddrArray from "mozilla/net/PDNSParams.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -19,13 +17,13 @@ namespace net {
|
|||
struct DNSRecord
|
||||
{
|
||||
nsCString canonicalName;
|
||||
NetAddr[] addrs;
|
||||
NetAddrArray addrs;
|
||||
};
|
||||
|
||||
union DNSRequestResponse
|
||||
{
|
||||
DNSRecord;
|
||||
IPCTypeRecord; // The result of a by-type query
|
||||
nsCString[]; // The result of a by-type query
|
||||
nsresult; // if error
|
||||
};
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ nsresult TRR::DohEncode(nsCString& aBody, bool aDisableECS) {
|
|||
offset += labelLength + 1; // move over label and dot
|
||||
} while (true);
|
||||
|
||||
aBody += static_cast<uint8_t>(mType >> 8); // upper 8 bit TYPE
|
||||
aBody += '\0'; // upper 8 bit TYPE
|
||||
aBody += static_cast<uint8_t>(mType);
|
||||
aBody += '\0'; // upper 8 bit CLASS
|
||||
aBody += kDNS_CLASS_IN; // IN - "the Internet"
|
||||
|
@ -235,8 +235,7 @@ nsresult TRR::SendHTTPRequest() {
|
|||
// This is essentially the "run" method - created from nsHostResolver
|
||||
|
||||
if ((mType != TRRTYPE_A) && (mType != TRRTYPE_AAAA) &&
|
||||
(mType != TRRTYPE_NS) && (mType != TRRTYPE_TXT) &&
|
||||
(mType != TRRTYPE_HTTPSSVC)) {
|
||||
(mType != TRRTYPE_NS) && (mType != TRRTYPE_TXT)) {
|
||||
// limit the calling interface because nsHostResolver has explicit slots for
|
||||
// these types
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -256,10 +255,10 @@ nsresult TRR::SendHTTPRequest() {
|
|||
}
|
||||
// not really an error but no TRR is issued
|
||||
return NS_ERROR_UNKNOWN_HOST;
|
||||
}
|
||||
|
||||
if (UseDefaultServer() && (mType == TRRTYPE_A)) {
|
||||
Telemetry::Accumulate(Telemetry::DNS_TRR_BLACKLISTED, false);
|
||||
} else {
|
||||
if (UseDefaultServer() && (mType == TRRTYPE_A)) {
|
||||
Telemetry::Accumulate(Telemetry::DNS_TRR_BLACKLISTED, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,7 +576,7 @@ nsresult TRR::ReceivePush(nsIHttpChannel* pushed, nsHostRecord* pushedRec) {
|
|||
}
|
||||
|
||||
if ((mType != TRRTYPE_A) && (mType != TRRTYPE_AAAA) &&
|
||||
(mType != TRRTYPE_TXT) && (mType != TRRTYPE_HTTPSSVC)) {
|
||||
(mType != TRRTYPE_TXT)) {
|
||||
LOG(("TRR::ReceivePush unknown type %d\n", mType));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -586,18 +585,13 @@ nsresult TRR::ReceivePush(nsIHttpChannel* pushed, nsHostRecord* pushedRec) {
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t type = nsIDNSService::RESOLVE_TYPE_DEFAULT;
|
||||
if (mType == TRRTYPE_TXT) {
|
||||
type = nsIDNSService::RESOLVE_TYPE_TXT;
|
||||
} else if (mType == TRRTYPE_HTTPSSVC) {
|
||||
type = nsIDNSService::RESOLVE_TYPE_HTTPSSVC;
|
||||
}
|
||||
|
||||
RefPtr<nsHostRecord> hostRecord;
|
||||
nsresult rv;
|
||||
rv = mHostResolver->GetHostRecord(
|
||||
mHost, EmptyCString(), type, pushedRec->flags, pushedRec->af,
|
||||
pushedRec->pb, pushedRec->originSuffix, getter_AddRefs(hostRecord));
|
||||
mHost, EmptyCString(),
|
||||
(mType != TRRTYPE_TXT) ? 0 : nsIDNSService::RESOLVE_TYPE_TXT,
|
||||
pushedRec->flags, pushedRec->af, pushedRec->pb, pushedRec->originSuffix,
|
||||
getter_AddRefs(hostRecord));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -647,11 +641,11 @@ TRR::OnStartRequest(nsIRequest* aRequest) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static uint16_t get16bit(const unsigned char* aData, unsigned int index) {
|
||||
static uint16_t get16bit(unsigned char* aData, int index) {
|
||||
return ((aData[index] << 8) | aData[index + 1]);
|
||||
}
|
||||
|
||||
static uint32_t get32bit(const unsigned char* aData, unsigned int index) {
|
||||
static uint32_t get32bit(unsigned char* aData, int index) {
|
||||
return (aData[index] << 24) | (aData[index + 1] << 16) |
|
||||
(aData[index + 2] << 8) | aData[index + 3];
|
||||
}
|
||||
|
@ -689,14 +683,14 @@ nsresult TRR::PassQName(unsigned int& index) {
|
|||
// GetQname: retrieves the qname (stores in 'aQname') and stores the index
|
||||
// after qname was parsed into the 'aIndex'.
|
||||
|
||||
nsresult TRR::GetQname(nsACString& aQname, unsigned int& aIndex) {
|
||||
nsresult TRR::GetQname(nsAutoCString& aQname, unsigned int& aIndex) {
|
||||
uint8_t clength = 0;
|
||||
unsigned int cindex = aIndex;
|
||||
unsigned int loop = 128; // a valid DNS name can never loop this much
|
||||
unsigned int endindex = 0; // index position after this data
|
||||
do {
|
||||
if (cindex >= mBodySize) {
|
||||
LOG(("TRR: bad Qname packet\n"));
|
||||
LOG(("TRR: bad cname packet\n"));
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
clength = static_cast<uint8_t>(mResponse[cindex]);
|
||||
|
@ -713,15 +707,13 @@ nsresult TRR::GetQname(nsACString& aQname, unsigned int& aIndex) {
|
|||
}
|
||||
cindex = newpos;
|
||||
continue;
|
||||
}
|
||||
if (clength & 0xc0) {
|
||||
} else if (clength & 0xc0) {
|
||||
// any of those bits set individually is an error
|
||||
LOG(("TRR: bad Qname packet\n"));
|
||||
LOG(("TRR: bad cname packet\n"));
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
} else {
|
||||
cindex++;
|
||||
}
|
||||
|
||||
cindex++;
|
||||
|
||||
if (clength) {
|
||||
if (!aQname.IsEmpty()) {
|
||||
aQname.Append(".");
|
||||
|
@ -787,7 +779,6 @@ nsresult TRR::DohDecode(nsCString& aHost) {
|
|||
while (questionRecords) {
|
||||
do {
|
||||
if (mBodySize < (index + 1)) {
|
||||
LOG(("TRR Decode 1 index: %u size: %u", index, mBodySize));
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
length = static_cast<uint8_t>(mResponse[index]);
|
||||
|
@ -796,8 +787,6 @@ nsresult TRR::DohDecode(nsCString& aHost) {
|
|||
host.Append(".");
|
||||
}
|
||||
if (mBodySize < (index + 1 + length)) {
|
||||
LOG(("TRR Decode 2 index: %u size: %u len: %u", index, mBodySize,
|
||||
length));
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
host.Append(((char*)mResponse) + index + 1, length);
|
||||
|
@ -805,7 +794,6 @@ nsresult TRR::DohDecode(nsCString& aHost) {
|
|||
index += 1 + length; // skip length byte + label
|
||||
} while (length);
|
||||
if (mBodySize < (index + 4)) {
|
||||
LOG(("TRR Decode 3 index: %u size: %u", index, mBodySize));
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
index += 4; // skip question's type, class
|
||||
|
@ -949,82 +937,11 @@ nsresult TRR::DohDecode(nsCString& aHost) {
|
|||
available -= characterStringLen;
|
||||
}
|
||||
|
||||
if (!mResult.is<TypeRecordTxt>()) {
|
||||
mResult = AsVariant(nsTArray<nsCString>());
|
||||
}
|
||||
|
||||
{
|
||||
auto& results = mResult.as<TypeRecordTxt>();
|
||||
results.AppendElement(txt);
|
||||
}
|
||||
if (mTTL > TTL) {
|
||||
mTTL = TTL;
|
||||
mTxt.AppendElement(txt);
|
||||
if (mTxtTtl > TTL) {
|
||||
mTxtTtl = TTL;
|
||||
}
|
||||
LOG(("TRR::DohDecode TXT host %s => %s\n", host.get(), txt.get()));
|
||||
|
||||
break;
|
||||
}
|
||||
case TRRTYPE_HTTPSSVC: {
|
||||
struct SVCB parsed;
|
||||
|
||||
unsigned int svcbIndex = index;
|
||||
CheckedInt<uint16_t> available = RDLENGTH;
|
||||
|
||||
// Should have at least 2 bytes for the priority and one for the
|
||||
// qname length.
|
||||
if (available.value() < 3) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
parsed.mSvcFieldPriority = get16bit(mResponse, svcbIndex);
|
||||
svcbIndex += 2;
|
||||
|
||||
rv = GetQname(parsed.mSvcDomainName, svcbIndex);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
available -= (svcbIndex - index);
|
||||
if (!available.isValid()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
while (available.value() >= 4) {
|
||||
// Every SvcFieldValues must have at least 4 bytes for the
|
||||
// SvcParamKey (2 bytes) and length of SvcParamValue (2 bytes)
|
||||
// If the length ever goes above the available data, meaning if
|
||||
// available ever underflows, then that is an error.
|
||||
struct SvcFieldValue value;
|
||||
uint16_t key = get16bit(mResponse, svcbIndex);
|
||||
svcbIndex += 2;
|
||||
|
||||
uint16_t len = get16bit(mResponse, svcbIndex);
|
||||
svcbIndex += 2;
|
||||
|
||||
available -= 4 + len;
|
||||
if (!available.isValid()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = ParseSvcParam(svcbIndex, key, value, len);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
svcbIndex += len;
|
||||
|
||||
// If this is an unknown key, we will simply ignore it.
|
||||
if (key == SvcParamKeyNone || key > SvcParamKeyLast) {
|
||||
continue;
|
||||
}
|
||||
parsed.mSvcFieldValue.AppendElement(value);
|
||||
}
|
||||
|
||||
if (!mResult.is<TypeRecordHTTPSSVC>()) {
|
||||
mResult = mozilla::AsVariant(nsTArray<SVCB>());
|
||||
}
|
||||
{
|
||||
auto& results = mResult.as<TypeRecordHTTPSSVC>();
|
||||
results.AppendElement(parsed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1111,7 +1028,7 @@ nsresult TRR::DohDecode(nsCString& aHost) {
|
|||
}
|
||||
|
||||
if ((mType != TRRTYPE_NS) && mCname.IsEmpty() &&
|
||||
!mDNS.mAddresses.getFirst() && mResult.is<TypeRecordEmpty>()) {
|
||||
!mDNS.mAddresses.getFirst() && mTxt.IsEmpty()) {
|
||||
// no entries were stored!
|
||||
LOG(("TRR: No entries were stored!\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1119,88 +1036,8 @@ nsresult TRR::DohDecode(nsCString& aHost) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TRR::ParseSvcParam(unsigned int svcbIndex, uint16_t key,
|
||||
SvcFieldValue& field, uint16_t length) {
|
||||
switch (key) {
|
||||
case SvcParamKeyAlpn: {
|
||||
field.mValue = AsVariant(SvcParamAlpn{
|
||||
.mValue = nsCString((const char*)(&mResponse[svcbIndex]), length)});
|
||||
break;
|
||||
}
|
||||
case SvcParamKeyNoDefaultAlpn: {
|
||||
if (length != 0) {
|
||||
// This key should not contain a value
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
field.mValue = AsVariant(SvcParamNoDefaultAlpn{});
|
||||
break;
|
||||
}
|
||||
case SvcParamKeyPort: {
|
||||
if (length != 2) {
|
||||
// This key should only encode a uint16_t
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
field.mValue =
|
||||
AsVariant(SvcParamPort{.mValue = get16bit(mResponse, svcbIndex)});
|
||||
break;
|
||||
}
|
||||
case SvcParamKeyIpv4Hint: {
|
||||
if (length % 4 != 0) {
|
||||
// This key should only encode IPv4 addresses
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
field.mValue = AsVariant(SvcParamIpv4Hint());
|
||||
auto& ipv4array = field.mValue.as<SvcParamIpv4Hint>().mValue;
|
||||
while (length > 0) {
|
||||
NetAddr addr = {.inet = {.family = AF_INET,
|
||||
.port = 0,
|
||||
.ip = ntohl(get32bit(mResponse, svcbIndex))}};
|
||||
ipv4array.AppendElement(addr);
|
||||
length -= 4;
|
||||
svcbIndex += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SvcParamKeyEsniConfig: {
|
||||
field.mValue = AsVariant(SvcParamEsniConfig{
|
||||
.mValue = nsCString((const char*)(&mResponse[svcbIndex]), length)});
|
||||
break;
|
||||
}
|
||||
case SvcParamKeyIpv6Hint: {
|
||||
if (length % 16 != 0) {
|
||||
// This key should only encode IPv6 addresses
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
field.mValue = AsVariant(SvcParamIpv6Hint());
|
||||
auto& ipv6array = field.mValue.as<SvcParamIpv6Hint>().mValue;
|
||||
while (length > 0) {
|
||||
NetAddr addr = {{.family = 0, .data = {0}}};
|
||||
addr.inet6.family = AF_INET6;
|
||||
addr.inet6.port = 0; // unknown
|
||||
addr.inet6.flowinfo = 0; // unknown
|
||||
addr.inet6.scope_id = 0; // unknown
|
||||
for (int i = 0; i < 16; i++, svcbIndex++) {
|
||||
addr.inet6.ip.u8[i] = mResponse[svcbIndex];
|
||||
}
|
||||
ipv6array.AppendElement(addr);
|
||||
length -= 16;
|
||||
// no need to increase svcbIndex - we did it in the for above.
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Unespected type. We'll just ignore it.
|
||||
return NS_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TRR::ReturnData(nsIChannel* aChannel) {
|
||||
if (mType != TRRTYPE_TXT && mType != TRRTYPE_HTTPSSVC) {
|
||||
if (mType != TRRTYPE_TXT) {
|
||||
// create and populate an AddrInfo instance to pass on
|
||||
RefPtr<AddrInfo> ai(new AddrInfo(mHost, mType));
|
||||
DOHaddr* item;
|
||||
|
@ -1242,7 +1079,7 @@ nsresult TRR::ReturnData(nsIChannel* aChannel) {
|
|||
mHostResolver = nullptr;
|
||||
mRec = nullptr;
|
||||
} else {
|
||||
(void)mHostResolver->CompleteLookupByType(mRec, NS_OK, mResult, mTTL, mPB);
|
||||
(void)mHostResolver->CompleteLookupByType(mRec, NS_OK, &mTxt, mTxtTtl, mPB);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1252,9 +1089,8 @@ nsresult TRR::FailData(nsresult error) {
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mType == TRRTYPE_TXT || mType == TRRTYPE_HTTPSSVC) {
|
||||
TypeRecordResultType empty(Nothing{});
|
||||
(void)mHostResolver->CompleteLookupByType(mRec, error, empty, 0, mPB);
|
||||
if (mType == TRRTYPE_TXT) {
|
||||
(void)mHostResolver->CompleteLookupByType(mRec, error, nullptr, 0, mPB);
|
||||
} else {
|
||||
// create and populate an TRR AddrInfo instance to pass on to signal that
|
||||
// this comes from TRR
|
||||
|
@ -1274,7 +1110,7 @@ nsresult TRR::On200Response(nsIChannel* aChannel) {
|
|||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!mDNS.mAddresses.getFirst() && !mCname.IsEmpty() &&
|
||||
mType != TRRTYPE_TXT && mType != TRRTYPE_HTTPSSVC) {
|
||||
mType != TRRTYPE_TXT) {
|
||||
nsCString cname = mCname;
|
||||
LOG(("TRR: check for CNAME record for %s within previous response\n",
|
||||
cname.get()));
|
||||
|
@ -1414,8 +1250,8 @@ TRR::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult DOHresp::Add(uint32_t TTL, unsigned char* dns, unsigned int index,
|
||||
uint16_t len, bool aLocalAllowed) {
|
||||
nsresult DOHresp::Add(uint32_t TTL, unsigned char* dns, int index, uint16_t len,
|
||||
bool aLocalAllowed) {
|
||||
auto doh = MakeUnique<DOHaddr>();
|
||||
NetAddr* addr = &doh->mNet;
|
||||
if (4 == len) {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef mozilla_net_TRR_h
|
||||
#define mozilla_net_TRR_h
|
||||
|
||||
#include "mozilla/net/DNSByTypeRecord.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIHttpPushListener.h"
|
||||
|
@ -26,7 +25,6 @@ enum TrrType {
|
|||
TRRTYPE_CNAME = 5,
|
||||
TRRTYPE_AAAA = 28,
|
||||
TRRTYPE_TXT = 16,
|
||||
TRRTYPE_HTTPSSVC = 65345,
|
||||
};
|
||||
|
||||
class DOHaddr : public LinkedListElement<DOHaddr> {
|
||||
|
@ -47,8 +45,8 @@ class DOHresp {
|
|||
delete el;
|
||||
}
|
||||
}
|
||||
nsresult Add(uint32_t TTL, unsigned char* dns, unsigned int index,
|
||||
uint16_t len, bool aLocalAllowed);
|
||||
nsresult Add(uint32_t TTL, unsigned char* dns, int index, uint16_t len,
|
||||
bool aLocalAllowed);
|
||||
LinkedList<DOHaddr> mAddresses;
|
||||
};
|
||||
|
||||
|
@ -82,6 +80,7 @@ class TRR : public Runnable,
|
|||
mFailed(false),
|
||||
mCnameLoop(kCnameChaseMax),
|
||||
mAllowRFC1918(false),
|
||||
mTxtTtl(UINT32_MAX),
|
||||
mOriginSuffix(aRec->originSuffix) {
|
||||
mHost = aRec->host;
|
||||
mPB = aRec->pb;
|
||||
|
@ -101,6 +100,7 @@ class TRR : public Runnable,
|
|||
mPB(aPB),
|
||||
mCnameLoop(aLoopCount),
|
||||
mAllowRFC1918(false),
|
||||
mTxtTtl(UINT32_MAX),
|
||||
mOriginSuffix(aRec ? aRec->originSuffix : EmptyCString()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "TRR must be in parent");
|
||||
}
|
||||
|
@ -114,7 +114,8 @@ class TRR : public Runnable,
|
|||
mFailed(false),
|
||||
mPB(aPB),
|
||||
mCnameLoop(kCnameChaseMax),
|
||||
mAllowRFC1918(false) {
|
||||
mAllowRFC1918(false),
|
||||
mTxtTtl(UINT32_MAX) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "TRR must be in parent");
|
||||
}
|
||||
|
||||
|
@ -131,6 +132,7 @@ class TRR : public Runnable,
|
|||
mPB(aPB),
|
||||
mCnameLoop(kCnameChaseMax),
|
||||
mAllowRFC1918(false),
|
||||
mTxtTtl(UINT32_MAX),
|
||||
mOriginSuffix(aOriginSuffix) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "TRR must be in parent");
|
||||
}
|
||||
|
@ -145,9 +147,9 @@ class TRR : public Runnable,
|
|||
private:
|
||||
~TRR() = default;
|
||||
nsresult SendHTTPRequest();
|
||||
nsresult DohEncode(nsCString& aBody, bool aDisableECS);
|
||||
nsresult DohEncode(nsCString& target, bool aDisableECS);
|
||||
nsresult PassQName(unsigned int& index);
|
||||
nsresult GetQname(nsACString& aQname, unsigned int& aIndex);
|
||||
nsresult GetQname(nsAutoCString& aQname, unsigned int& aIndex);
|
||||
nsresult DohDecode(nsCString& aHost);
|
||||
nsresult ReturnData(nsIChannel* aChannel);
|
||||
|
||||
|
@ -171,9 +173,6 @@ class TRR : public Runnable,
|
|||
static nsresult SetupTRRServiceChannelInternal(nsIHttpChannel* aChannel,
|
||||
bool aUseGet);
|
||||
|
||||
nsresult ParseSvcParam(unsigned int svcbIndex, uint16_t key,
|
||||
SvcFieldValue& field, uint16_t length);
|
||||
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
enum TrrType mType;
|
||||
TimeStamp mStartTime;
|
||||
|
@ -186,9 +185,8 @@ class TRR : public Runnable,
|
|||
nsCString mCname;
|
||||
uint32_t mCnameLoop; // loop detection counter
|
||||
bool mAllowRFC1918;
|
||||
|
||||
uint32_t mTTL = UINT32_MAX;
|
||||
TypeRecordResultType mResult = mozilla::AsVariant(Nothing());
|
||||
nsTArray<nsCString> mTxt;
|
||||
uint32_t mTxtTtl;
|
||||
|
||||
// keep a copy of the originSuffix for the cases where mRec == nullptr */
|
||||
const nsCString mOriginSuffix;
|
||||
|
|
|
@ -297,6 +297,7 @@ nsresult TRRService::ReadPrefs(const char* name) {
|
|||
}
|
||||
if (!name || !strcmp(name, TRR_PREF("uri")) ||
|
||||
!strcmp(name, kRolloutURIPref)) {
|
||||
|
||||
mURIPrefHasUserValue = Preferences::HasUserValue(TRR_PREF("uri"));
|
||||
Preferences::GetCString(TRR_PREF("uri"), mURIPref);
|
||||
Preferences::GetCString(kRolloutURIPref, mRolloutURIPref);
|
||||
|
@ -1026,8 +1027,8 @@ AHostResolver::LookupStatus TRRService::CompleteLookup(
|
|||
}
|
||||
|
||||
AHostResolver::LookupStatus TRRService::CompleteLookupByType(
|
||||
nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
|
||||
uint32_t aTtl, bool aPb) {
|
||||
nsHostRecord*, nsresult, const nsTArray<nsCString>* aResult, uint32_t aTtl,
|
||||
bool aPb) {
|
||||
return LOOKUP_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,8 +53,8 @@ class TRRService : public nsIObserver,
|
|||
bool pb,
|
||||
const nsACString& aOriginSuffix) override;
|
||||
LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
|
||||
mozilla::net::TypeRecordResultType&,
|
||||
uint32_t, bool pb) override;
|
||||
const nsTArray<nsCString>*, uint32_t,
|
||||
bool pb) override;
|
||||
void TRRBlacklist(const nsACString& host, const nsACString& originSuffix,
|
||||
bool privateBrowsing, bool aParentsToo);
|
||||
bool IsTRRBlacklisted(const nsACString& aHost,
|
||||
|
|
|
@ -38,13 +38,12 @@ EXPORTS += [
|
|||
EXPORTS.mozilla.net += [
|
||||
'ChildDNSService.h',
|
||||
'DNS.h',
|
||||
'DNSByTypeRecord.h',
|
||||
'DNSListenerProxy.h',
|
||||
'DNSRequestBase.h',
|
||||
'DNSRequestChild.h',
|
||||
'DNSRequestParent.h',
|
||||
'HTTPSSVC.h',
|
||||
'IDNBlocklistUtils.h',
|
||||
'PDNSParams.h',
|
||||
'TRRService.h',
|
||||
]
|
||||
|
||||
|
@ -60,7 +59,6 @@ UNIFIED_SOURCES += [
|
|||
'DNSRequestChild.cpp',
|
||||
'DNSRequestParent.cpp',
|
||||
'GetAddrInfo.cpp',
|
||||
'HTTPSSVC.cpp',
|
||||
'IDNBlocklistUtils.cpp',
|
||||
'nsDNSService2.cpp',
|
||||
'nsIDNService.cpp',
|
||||
|
|
|
@ -320,15 +320,11 @@ nsDNSRecord::ReportUnusable(uint16_t aPort) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsDNSByTypeRecord : public nsIDNSByTypeRecord,
|
||||
public nsIDNSTXTRecord,
|
||||
public nsIDNSHTTPSSVCRecord {
|
||||
class nsDNSByTypeRecord : public nsIDNSByTypeRecord {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_FORWARD_SAFE_NSIDNSRECORD(((nsIDNSRecord*)nullptr))
|
||||
NS_DECL_NSIDNSBYTYPERECORD
|
||||
NS_DECL_NSIDNSTXTRECORD
|
||||
NS_DECL_NSIDNSHTTPSSVCRECORD
|
||||
|
||||
explicit nsDNSByTypeRecord(nsHostRecord* hostRecord) {
|
||||
mHostRecord = do_QueryObject(hostRecord);
|
||||
|
@ -339,35 +335,19 @@ class nsDNSByTypeRecord : public nsIDNSByTypeRecord,
|
|||
RefPtr<TypeHostRecord> mHostRecord;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsDNSByTypeRecord, nsIDNSRecord, nsIDNSByTypeRecord,
|
||||
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSByTypeRecord::GetType(uint32_t* aType) {
|
||||
*aType = mHostRecord->GetType();
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMPL_ISUPPORTS(nsDNSByTypeRecord, nsIDNSRecord, nsIDNSByTypeRecord)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSByTypeRecord::GetRecords(nsTArray<nsCString>& aRecords) {
|
||||
// deep copy
|
||||
return mHostRecord->GetRecords(aRecords);
|
||||
mHostRecord->GetRecords(aRecords);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSByTypeRecord::GetRecordsAsOneString(nsACString& aRecords) {
|
||||
// deep copy
|
||||
return mHostRecord->GetRecordsAsOneString(aRecords);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSByTypeRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
|
||||
return mHostRecord->GetRecords(aRecords);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSByTypeRecord::GetResults(mozilla::net::TypeRecordResultType* aResults) {
|
||||
*aResults = mHostRecord->GetResults();
|
||||
mHostRecord->GetRecordsAsOneString(aRecords);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -888,8 +868,7 @@ nsresult nsDNSService::AsyncResolveInternal(
|
|||
|
||||
if (!res) return NS_ERROR_OFFLINE;
|
||||
|
||||
if ((type != RESOLVE_TYPE_DEFAULT) && (type != RESOLVE_TYPE_TXT) &&
|
||||
(type != RESOLVE_TYPE_HTTPSSVC)) {
|
||||
if ((type != RESOLVE_TYPE_DEFAULT) && (type != RESOLVE_TYPE_TXT)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
|
|
@ -494,8 +494,7 @@ AddrHostRecord::DnsPriority AddrHostRecord::GetPriority(uint16_t aFlags) {
|
|||
return AddrHostRecord::DNS_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord,
|
||||
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
|
||||
NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord)
|
||||
|
||||
TypeHostRecord::TypeHostRecord(const nsHostKey& key)
|
||||
: nsHostRecord(key),
|
||||
|
@ -505,32 +504,22 @@ TypeHostRecord::TypeHostRecord(const nsHostKey& key)
|
|||
TypeHostRecord::~TypeHostRecord() { mCallbacks.clear(); }
|
||||
|
||||
bool TypeHostRecord::HasUsableResultInternal() const {
|
||||
return !mResults.is<Nothing>();
|
||||
return !mResults.IsEmpty();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP TypeHostRecord::GetRecords(nsTArray<nsCString>& aRecords) {
|
||||
void TypeHostRecord::GetRecords(nsTArray<nsCString>& aRecords) {
|
||||
// deep copy
|
||||
MutexAutoLock lock(mResultsLock);
|
||||
aRecords = mResults;
|
||||
}
|
||||
|
||||
void TypeHostRecord::GetRecordsAsOneString(nsACString& aRecords) {
|
||||
// deep copy
|
||||
MutexAutoLock lock(mResultsLock);
|
||||
|
||||
if (!mResults.is<TypeRecordTxt>()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
for (uint32_t i = 0; i < mResults.Length(); i++) {
|
||||
aRecords.Append(mResults[i]);
|
||||
}
|
||||
aRecords = mResults.as<nsTArray<nsCString>>();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP TypeHostRecord::GetRecordsAsOneString(nsACString& aRecords) {
|
||||
// deep copy
|
||||
MutexAutoLock lock(mResultsLock);
|
||||
|
||||
if (!mResults.is<TypeRecordTxt>()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
auto& results = mResults.as<nsTArray<nsCString>>();
|
||||
for (uint32_t i = 0; i < results.Length(); i++) {
|
||||
aRecords.Append(results[i]);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
size_t TypeHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
||||
|
@ -549,40 +538,6 @@ void TypeHostRecord::Cancel() {
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t TypeHostRecord::GetType() {
|
||||
MutexAutoLock lock(mResultsLock);
|
||||
|
||||
return mResults.match(
|
||||
[](TypeRecordEmpty&) {
|
||||
MOZ_ASSERT(false, "This should never be the case");
|
||||
return nsIDNSService::RESOLVE_TYPE_DEFAULT;
|
||||
},
|
||||
[](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
|
||||
[](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
|
||||
}
|
||||
|
||||
TypeRecordResultType TypeHostRecord::GetResults() {
|
||||
MutexAutoLock lock(mResultsLock);
|
||||
return mResults;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TypeHostRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
|
||||
MutexAutoLock lock(mResultsLock);
|
||||
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
||||
|
||||
for (const SVCB& r : results) {
|
||||
RefPtr<nsISVCBRecord> rec = new mozilla::net::SVCBRecord(r);
|
||||
aRecords.AppendElement(rec);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static const char kPrefGetTtl[] = "network.dns.get-ttl";
|
||||
|
@ -705,8 +660,7 @@ void nsHostResolver::ClearPendingQueue(
|
|||
CompleteLookup(rec, NS_ERROR_ABORT, nullptr, rec->pb,
|
||||
rec->originSuffix);
|
||||
} else {
|
||||
mozilla::net::TypeRecordResultType empty(Nothing{});
|
||||
CompleteLookupByType(rec, NS_ERROR_ABORT, empty, 0, rec->pb);
|
||||
CompleteLookupByType(rec, NS_ERROR_ABORT, nullptr, 0, rec->pb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1341,14 +1295,7 @@ nsresult nsHostResolver::TrrLookup(nsHostRecord* aRec, TRR* pushedTRR) {
|
|||
} while (sendAgain);
|
||||
} else {
|
||||
typeRec->mStart = TimeStamp::Now();
|
||||
enum TrrType rectype;
|
||||
|
||||
// XXX this could use a more extensible approach.
|
||||
if (rec->type == nsIDNSService::RESOLVE_TYPE_TXT) {
|
||||
rectype = TRRTYPE_TXT;
|
||||
} else if (rec->type == nsIDNSService::RESOLVE_TYPE_HTTPSSVC) {
|
||||
rectype = TRRTYPE_HTTPSSVC;
|
||||
}
|
||||
enum TrrType rectype = TRRTYPE_TXT;
|
||||
|
||||
if (pushedTRR) {
|
||||
rectype = pushedTRR->Type();
|
||||
|
@ -2016,8 +1963,8 @@ nsHostResolver::LookupStatus nsHostResolver::CompleteLookup(
|
|||
}
|
||||
|
||||
nsHostResolver::LookupStatus nsHostResolver::CompleteLookupByType(
|
||||
nsHostRecord* rec, nsresult status,
|
||||
mozilla::net::TypeRecordResultType& aResult, uint32_t aTtl, bool pb) {
|
||||
nsHostRecord* rec, nsresult status, const nsTArray<nsCString>* aResult,
|
||||
uint32_t aTtl, bool pb) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MOZ_ASSERT(rec);
|
||||
MOZ_ASSERT(rec->pb == pb);
|
||||
|
@ -2039,23 +1986,18 @@ nsHostResolver::LookupStatus nsHostResolver::CompleteLookupByType(
|
|||
LOG(("nsHostResolver::CompleteLookupByType record %p [%s] status %x\n",
|
||||
typeRec.get(), typeRec->host.get(), (unsigned int)status));
|
||||
typeRec->SetExpiration(TimeStamp::NowLoRes(), NEGATIVE_RECORD_LIFETIME, 0);
|
||||
MOZ_ASSERT(aResult.is<TypeRecordEmpty>());
|
||||
MOZ_ASSERT(!aResult);
|
||||
status = NS_ERROR_UNKNOWN_HOST;
|
||||
typeRec->negative = true;
|
||||
Telemetry::Accumulate(Telemetry::DNS_BY_TYPE_FAILED_LOOKUP_TIME, duration);
|
||||
} else {
|
||||
size_t recordCount = 0;
|
||||
if (aResult.is<TypeRecordTxt>()) {
|
||||
recordCount = aResult.as<TypeRecordTxt>().Length();
|
||||
} else if (aResult.is<TypeRecordHTTPSSVC>()) {
|
||||
recordCount = aResult.as<TypeRecordHTTPSSVC>().Length();
|
||||
}
|
||||
MOZ_ASSERT(aResult);
|
||||
LOG(
|
||||
("nsHostResolver::CompleteLookupByType record %p [%s], number of "
|
||||
"records %zu\n",
|
||||
typeRec.get(), typeRec->host.get(), recordCount));
|
||||
typeRec.get(), typeRec->host.get(), aResult->Length()));
|
||||
MutexAutoLock typeLock(typeRec->mResultsLock);
|
||||
typeRec->mResults = aResult;
|
||||
typeRec->mResults = *aResult;
|
||||
typeRec->SetExpiration(TimeStamp::NowLoRes(), aTtl, mDefaultGracePeriod);
|
||||
typeRec->negative = false;
|
||||
Telemetry::Accumulate(Telemetry::DNS_BY_TYPE_SUCCEEDED_LOOKUP_TIME,
|
||||
|
|
|
@ -25,9 +25,6 @@
|
|||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsIThreadPool.h"
|
||||
#include "mozilla/net/NetworkConnectivityService.h"
|
||||
#include "nsIDNSByTypeRecord.h"
|
||||
#include "mozilla/net/DNSByTypeRecord.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
class nsHostResolver;
|
||||
class nsResolveHostCallback;
|
||||
|
@ -285,18 +282,15 @@ NS_DEFINE_STATIC_IID_ACCESSOR(AddrHostRecord, ADDRHOSTRECORD_IID)
|
|||
} \
|
||||
}
|
||||
|
||||
class TypeHostRecord final : public nsHostRecord,
|
||||
public nsIDNSTXTRecord,
|
||||
public nsIDNSHTTPSSVCRecord {
|
||||
class TypeHostRecord final : public nsHostRecord {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(TYPEHOSTRECORD_IID)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDNSTXTRECORD
|
||||
NS_DECL_NSIDNSHTTPSSVCRECORD
|
||||
|
||||
void GetRecords(nsTArray<nsCString>& aRecords);
|
||||
void GetRecordsAsOneString(nsACString& aRecords);
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
|
||||
uint32_t GetType();
|
||||
mozilla::net::TypeRecordResultType GetResults();
|
||||
|
||||
private:
|
||||
friend class nsHostResolver;
|
||||
|
@ -314,7 +308,7 @@ class TypeHostRecord final : public nsHostRecord,
|
|||
mozilla::Mutex mTrrLock; // lock when accessing the mTrr pointer
|
||||
RefPtr<mozilla::net::TRR> mTrr;
|
||||
|
||||
mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
|
||||
nsTArray<nsCString> mResults;
|
||||
mozilla::Mutex mResultsLock;
|
||||
|
||||
// When the lookups of this record started (for telemetry).
|
||||
|
@ -386,9 +380,9 @@ class AHostResolver {
|
|||
virtual LookupStatus CompleteLookup(nsHostRecord*, nsresult,
|
||||
mozilla::net::AddrInfo*, bool pb,
|
||||
const nsACString& aOriginsuffix) = 0;
|
||||
virtual LookupStatus CompleteLookupByType(
|
||||
nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
|
||||
uint32_t aTtl, bool pb) = 0;
|
||||
virtual LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
|
||||
const nsTArray<nsCString>* aResult,
|
||||
uint32_t aTtl, bool pb) = 0;
|
||||
virtual nsresult GetHostRecord(const nsACString& host,
|
||||
const nsACString& aTrrServer, uint16_t type,
|
||||
uint16_t flags, uint16_t af, bool pb,
|
||||
|
@ -503,7 +497,7 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
bool pb,
|
||||
const nsACString& aOriginsuffix) override;
|
||||
LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
|
||||
mozilla::net::TypeRecordResultType& aResult,
|
||||
const nsTArray<nsCString>* aResult,
|
||||
uint32_t aTtl, bool pb) override;
|
||||
nsresult GetHostRecord(const nsACString& host, const nsACString& trrServer,
|
||||
uint16_t type, uint16_t flags, uint16_t af, bool pb,
|
||||
|
|
|
@ -5,40 +5,13 @@
|
|||
#include "nsIDNSRecord.idl"
|
||||
|
||||
%{ C++
|
||||
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "nsStringFwd.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <typename... Ts> class Variant;
|
||||
struct Nothing;
|
||||
|
||||
namespace net {
|
||||
struct SVCB;
|
||||
using TypeRecordResultType =
|
||||
Variant<Nothing, nsTArray<nsCString>, nsTArray<SVCB>>;
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
[ref] native CStringArrayRef(nsTArray<nsCString>);
|
||||
native TypeResult(mozilla::net::TypeRecordResultType);
|
||||
|
||||
[scriptable, uuid(5d13241b-9d46-448a-90d8-77c418491026)]
|
||||
interface nsIDNSByTypeRecord : nsIDNSRecord
|
||||
{
|
||||
/**
|
||||
* Returns DNS request type that was made for this request.
|
||||
*/
|
||||
readonly attribute unsigned long type;
|
||||
|
||||
[noscript] readonly attribute TypeResult results;
|
||||
};
|
||||
|
||||
[scriptable, uuid(2a71750d-cb21-45f1-9e1c-666d18dd7645)]
|
||||
interface nsIDNSTXTRecord : nsISupports
|
||||
{
|
||||
CStringArrayRef getRecords();
|
||||
|
||||
|
@ -47,50 +20,3 @@ interface nsIDNSTXTRecord : nsISupports
|
|||
*/
|
||||
ACString getRecordsAsOneString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(2979ceaa-9c7e-49de-84b8-ea81c16aebf1)]
|
||||
interface nsISVCParam : nsISupports {
|
||||
readonly attribute uint16_t type;
|
||||
};
|
||||
|
||||
[scriptable, uuid(0dc58309-4d67-4fc4-a4e3-38dbde9d9f4c)]
|
||||
interface nsISVCParamAlpn : nsISupports {
|
||||
readonly attribute ACString alpn;
|
||||
};
|
||||
|
||||
[scriptable, uuid(b3ed89c3-2ae6-4c92-8176-b76bc2437fcb)]
|
||||
interface nsISVCParamNoDefaultAlpn : nsISupports {
|
||||
};
|
||||
|
||||
[scriptable, uuid(a37c7bcb-bfcd-4ab4-b826-cc583859ba73)]
|
||||
interface nsISVCParamPort : nsISupports {
|
||||
readonly attribute uint16_t port;
|
||||
};
|
||||
|
||||
[scriptable, uuid(d3163d2f-0bbe-47d4-bcac-db3fb1433b39)]
|
||||
interface nsISVCParamIPv4Hint : nsISupports {
|
||||
readonly attribute Array<nsINetAddr> ipv4Hint;
|
||||
};
|
||||
|
||||
[scriptable, uuid(1f31e41d-b6d8-4796-b12a-82ef8d2b0e43)]
|
||||
interface nsISVCParamEsniConfig : nsISupports {
|
||||
readonly attribute ACString esniConfig;
|
||||
};
|
||||
|
||||
[scriptable, uuid(5100bce4-9d3b-42e1-a3c9-0f386bbc9dad)]
|
||||
interface nsISVCParamIPv6Hint : nsISupports {
|
||||
readonly attribute Array<nsINetAddr> ipv6Hint;
|
||||
};
|
||||
|
||||
[scriptable, uuid(a4da5645-2160-4439-bd11-540a2d26c989)]
|
||||
interface nsISVCBRecord : nsISupports {
|
||||
readonly attribute uint16_t priority;
|
||||
readonly attribute ACString name;
|
||||
readonly attribute Array<nsISVCParam> values;
|
||||
};
|
||||
|
||||
[scriptable, uuid(5b649e95-e0d3-422b-99a6-79d70a041387)]
|
||||
interface nsIDNSHTTPSSVCRecord : nsISupports
|
||||
{
|
||||
readonly attribute Array<nsISVCBRecord> records;
|
||||
};
|
||||
|
|
|
@ -406,7 +406,6 @@ interface nsIDNSService : nsISupports
|
|||
*/
|
||||
const unsigned long RESOLVE_TYPE_DEFAULT = 0;
|
||||
const unsigned long RESOLVE_TYPE_TXT = 16;
|
||||
const unsigned long RESOLVE_TYPE_HTTPSSVC = 65345;
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -89,7 +89,15 @@ class DNSListener {
|
|||
});
|
||||
}
|
||||
onLookupComplete(inRequest, inRecord, inStatus) {
|
||||
this.resolve([inRequest, inRecord, inStatus]);
|
||||
let txtRec;
|
||||
try {
|
||||
txtRec = inRecord.QueryInterface(Ci.nsIDNSByTypeRecord);
|
||||
} catch (e) {}
|
||||
if (txtRec) {
|
||||
this.resolve([inRequest, txtRec, inStatus, "onLookupByTypeComplete"]);
|
||||
} else {
|
||||
this.resolve([inRequest, inRecord, inStatus, "onLookupComplete"]);
|
||||
}
|
||||
}
|
||||
// So we can await this as a promise.
|
||||
then() {
|
||||
|
@ -105,7 +113,7 @@ add_task(async function testEsniRequest() {
|
|||
// use the h2 server as DOH provider
|
||||
prefs.setCharPref(
|
||||
"network.trr.uri",
|
||||
"https://foo.example.com:" + h2Port + "/doh"
|
||||
"https://foo.example.com:" + h2Port + "/esni-dns"
|
||||
);
|
||||
|
||||
let listenerEsni = new DNSListener();
|
||||
|
@ -118,12 +126,11 @@ add_task(async function testEsniRequest() {
|
|||
defaultOriginAttributes
|
||||
);
|
||||
|
||||
let [inRequest, inRecord, inStatus] = await listenerEsni;
|
||||
let [inRequest, inRecord, inStatus, inType] = await listenerEsni;
|
||||
Assert.equal(inType, "onLookupByTypeComplete", "check correct type");
|
||||
Assert.equal(inRequest, request, "correct request was used");
|
||||
Assert.equal(inStatus, Cr.NS_OK, "status OK");
|
||||
let answer = inRecord
|
||||
.QueryInterface(Ci.nsIDNSTXTRecord)
|
||||
.getRecordsAsOneString();
|
||||
let answer = inRecord.getRecordsAsOneString();
|
||||
Assert.equal(answer, test_answer, "got correct answer");
|
||||
});
|
||||
|
||||
|
@ -142,7 +149,8 @@ add_task(async function testEsniPushPart1() {
|
|||
defaultOriginAttributes
|
||||
);
|
||||
|
||||
let [inRequest, inRecord, inStatus] = await listenerAddr;
|
||||
let [inRequest, inRecord, inStatus, inType] = await listenerAddr;
|
||||
Assert.equal(inType, "onLookupComplete", "check correct type");
|
||||
Assert.equal(inRequest, request, "correct request was used");
|
||||
Assert.equal(inStatus, Cr.NS_OK, "status OK");
|
||||
let answer = inRecord.getNextAddrAsString();
|
||||
|
@ -167,34 +175,10 @@ add_task(async function testEsniPushPart2() {
|
|||
defaultOriginAttributes
|
||||
);
|
||||
|
||||
let [inRequest, inRecord, inStatus] = await listenerEsni;
|
||||
let [inRequest, inRecord, inStatus, inType] = await listenerEsni;
|
||||
Assert.equal(inType, "onLookupByTypeComplete", "check correct type");
|
||||
Assert.equal(inRequest, request, "correct request was used");
|
||||
Assert.equal(inStatus, Cr.NS_OK, "status OK");
|
||||
let answer = inRecord
|
||||
.QueryInterface(Ci.nsIDNSTXTRecord)
|
||||
.getRecordsAsOneString();
|
||||
let answer = inRecord.getRecordsAsOneString();
|
||||
Assert.equal(answer, test_answer, "got correct answer");
|
||||
});
|
||||
|
||||
add_task(async function testEsniHTTPSSVC() {
|
||||
prefs.setCharPref(
|
||||
"network.trr.uri",
|
||||
"https://foo.example.com:" + h2Port + "/doh"
|
||||
);
|
||||
let listenerEsni = new DNSListener();
|
||||
let request = dns.asyncResolveByType(
|
||||
"httpssvc_esni.example.com",
|
||||
dns.RESOLVE_TYPE_HTTPSSVC,
|
||||
0,
|
||||
listenerEsni,
|
||||
mainThread,
|
||||
defaultOriginAttributes
|
||||
);
|
||||
|
||||
let [inRequest, inRecord, inStatus] = await listenerEsni;
|
||||
Assert.equal(inRequest, request, "correct request was used");
|
||||
Assert.equal(inStatus, Cr.NS_OK, "status OK");
|
||||
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
|
||||
let esni = answer[0].values[0].QueryInterface(Ci.nsISVCParamEsniConfig);
|
||||
Assert.equal(esni.esniConfig, "testytestystringstring", "got correct answer");
|
||||
});
|
||||
|
|
|
@ -1,207 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
let prefs;
|
||||
let h2Port;
|
||||
let listen;
|
||||
|
||||
function inChildProcess() {
|
||||
return (
|
||||
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
|
||||
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
|
||||
);
|
||||
}
|
||||
|
||||
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
|
||||
Ci.nsIDNSService
|
||||
);
|
||||
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
|
||||
Ci.nsIThreadManager
|
||||
);
|
||||
const mainThread = threadManager.currentThread;
|
||||
|
||||
const defaultOriginAttributes = {};
|
||||
|
||||
function setup() {
|
||||
let env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||
Ci.nsIEnvironment
|
||||
);
|
||||
h2Port = env.get("MOZHTTP2_PORT");
|
||||
Assert.notEqual(h2Port, null);
|
||||
Assert.notEqual(h2Port, "");
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
prefs.setBoolPref("network.security.esni.enabled", false);
|
||||
prefs.setBoolPref("network.http.spdy.enabled", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
|
||||
// the TRR server is on 127.0.0.1
|
||||
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
|
||||
|
||||
// make all native resolve calls "secretly" resolve localhost instead
|
||||
prefs.setBoolPref("network.dns.native-is-localhost", true);
|
||||
|
||||
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
|
||||
prefs.setIntPref("network.trr.mode", 2); // TRR first
|
||||
prefs.setBoolPref("network.trr.wait-for-portal", false);
|
||||
// don't confirm that TRR is working, just go!
|
||||
prefs.setCharPref("network.trr.confirmationNS", "skip");
|
||||
|
||||
// So we can change the pref without clearing the cache to check a pushed
|
||||
// record with a TRR path that fails.
|
||||
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
|
||||
|
||||
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
|
||||
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
|
||||
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||
Ci.nsIX509CertDB
|
||||
);
|
||||
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
|
||||
}
|
||||
|
||||
if (!inChildProcess()) {
|
||||
setup();
|
||||
registerCleanupFunction(() => {
|
||||
prefs.clearUserPref("network.security.esni.enabled");
|
||||
prefs.clearUserPref("network.http.spdy.enabled");
|
||||
prefs.clearUserPref("network.http.spdy.enabled.http2");
|
||||
prefs.clearUserPref("network.dns.localDomains");
|
||||
prefs.clearUserPref("network.dns.native-is-localhost");
|
||||
prefs.clearUserPref("network.trr.mode");
|
||||
prefs.clearUserPref("network.trr.uri");
|
||||
prefs.clearUserPref("network.trr.credentials");
|
||||
prefs.clearUserPref("network.trr.wait-for-portal");
|
||||
prefs.clearUserPref("network.trr.allow-rfc1918");
|
||||
prefs.clearUserPref("network.trr.useGET");
|
||||
prefs.clearUserPref("network.trr.confirmationNS");
|
||||
prefs.clearUserPref("network.trr.bootstrapAddress");
|
||||
prefs.clearUserPref("network.trr.blacklist-duration");
|
||||
prefs.clearUserPref("network.trr.request-timeout");
|
||||
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
|
||||
});
|
||||
}
|
||||
|
||||
class DNSListener {
|
||||
constructor() {
|
||||
this.promise = new Promise(resolve => {
|
||||
this.resolve = resolve;
|
||||
});
|
||||
}
|
||||
onLookupComplete(inRequest, inRecord, inStatus) {
|
||||
this.resolve([inRequest, inRecord, inStatus]);
|
||||
}
|
||||
// So we can await this as a promise.
|
||||
then() {
|
||||
return this.promise.then.apply(this.promise, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsIDNSListener,
|
||||
]);
|
||||
|
||||
add_task(async function testHTTPSSVC() {
|
||||
// use the h2 server as DOH provider
|
||||
if (!inChildProcess()) {
|
||||
prefs.setCharPref(
|
||||
"network.trr.uri",
|
||||
"https://foo.example.com:" + h2Port + "/httpssvc"
|
||||
);
|
||||
}
|
||||
|
||||
let listenerEsni = new DNSListener();
|
||||
let request = dns.asyncResolveByType(
|
||||
"test.httpssvc.com",
|
||||
dns.RESOLVE_TYPE_HTTPSSVC,
|
||||
0,
|
||||
listenerEsni,
|
||||
mainThread,
|
||||
defaultOriginAttributes
|
||||
);
|
||||
|
||||
let [inRequest, inRecord, inStatus] = await listenerEsni;
|
||||
Assert.equal(inRequest, request, "correct request was used");
|
||||
Assert.equal(inStatus, Cr.NS_OK, "status OK");
|
||||
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
|
||||
Assert.equal(answer[0].priority, 1);
|
||||
Assert.equal(answer[0].name, "h3pool");
|
||||
Assert.equal(answer[0].values.length, 6);
|
||||
Assert.equal(
|
||||
answer[0].values[0].QueryInterface(Ci.nsISVCParamAlpn).alpn,
|
||||
"h2,h3",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.ok(
|
||||
answer[0].values[1].QueryInterface(Ci.nsISVCParamNoDefaultAlpn),
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[0].values[2].QueryInterface(Ci.nsISVCParamPort).port,
|
||||
8888,
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[0].values[3].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[0]
|
||||
.address,
|
||||
"1.2.3.4",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[0].values[4].QueryInterface(Ci.nsISVCParamEsniConfig).esniConfig,
|
||||
"123...",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[0].values[5].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[0]
|
||||
.address,
|
||||
"::1",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(answer[1].priority, 2);
|
||||
Assert.equal(answer[1].name, "");
|
||||
Assert.equal(answer[1].values.length, 4);
|
||||
Assert.equal(
|
||||
answer[1].values[0].QueryInterface(Ci.nsISVCParamAlpn).alpn,
|
||||
"h2",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[1].values[1].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[0]
|
||||
.address,
|
||||
"1.2.3.4",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[1].values[1].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[1]
|
||||
.address,
|
||||
"5.6.7.8",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[1].values[2].QueryInterface(Ci.nsISVCParamEsniConfig).esniConfig,
|
||||
"abc...",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[1].values[3].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[0]
|
||||
.address,
|
||||
"::1",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(
|
||||
answer[1].values[3].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[1]
|
||||
.address,
|
||||
"fe80::794f:6d2c:3d5e:7836",
|
||||
"got correct answer"
|
||||
);
|
||||
Assert.equal(answer[2].priority, 3);
|
||||
Assert.equal(answer[2].name, "hello");
|
||||
Assert.equal(answer[2].values.length, 0);
|
||||
});
|
|
@ -425,4 +425,3 @@ skip-if = true || asan || tsan || os == 'win' || os =='android'
|
|||
[test_port_remapping.js]
|
||||
[test_dns_override.js]
|
||||
[test_no_cookies_after_last_pb_exit.js]
|
||||
[test_trr_httpssvc.js]
|
||||
|
|
|
@ -20,7 +20,15 @@ class DNSListener {
|
|||
});
|
||||
}
|
||||
onLookupComplete(inRequest, inRecord, inStatus) {
|
||||
this.resolve([inRequest, inRecord, inStatus]);
|
||||
let txtRec;
|
||||
try {
|
||||
txtRec = inRecord.QueryInterface(Ci.nsIDNSByTypeRecord);
|
||||
} catch (e) {}
|
||||
if (txtRec) {
|
||||
this.resolve([inRequest, txtRec, inStatus, "onLookupByTypeComplete"]);
|
||||
} else {
|
||||
this.resolve([inRequest, inRecord, inStatus, "onLookupComplete"]);
|
||||
}
|
||||
}
|
||||
// So we can await this as a promise.
|
||||
then() {
|
||||
|
@ -44,31 +52,10 @@ add_task(async function testEsniRequest() {
|
|||
defaultOriginAttributes
|
||||
);
|
||||
|
||||
let [inRequest, inRecord, inStatus] = await listenerEsni;
|
||||
let [inRequest, inRecord, inStatus, inType] = await listenerEsni;
|
||||
Assert.equal(inStatus, Cr.NS_OK, "status OK");
|
||||
Assert.equal(inRequest, request, "correct request was used");
|
||||
let answer = inRecord
|
||||
.QueryInterface(Ci.nsIDNSTXTRecord)
|
||||
.getRecordsAsOneString();
|
||||
Assert.equal(inType, "onLookupByTypeComplete", "check correct type");
|
||||
let answer = inRecord.getRecordsAsOneString();
|
||||
Assert.equal(answer, test_answer, "got correct answer");
|
||||
});
|
||||
|
||||
add_task(async function testEsniHTTPSSVC() {
|
||||
// use the h2 server as DOH provider
|
||||
let listenerEsni = new DNSListener();
|
||||
let request = dns.asyncResolveByType(
|
||||
"httpssvc_esni.example.com",
|
||||
dns.RESOLVE_TYPE_HTTPSSVC,
|
||||
0,
|
||||
listenerEsni,
|
||||
mainThread,
|
||||
defaultOriginAttributes
|
||||
);
|
||||
|
||||
let [inRequest, inRecord, inStatus] = await listenerEsni;
|
||||
Assert.equal(inRequest, request, "correct request was used");
|
||||
Assert.equal(inStatus, Cr.NS_OK, "status OK");
|
||||
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
|
||||
let esni = answer[0].values[0].QueryInterface(Ci.nsISVCParamEsniConfig);
|
||||
Assert.equal(esni.esniConfig, "testytestystringstring", "got correct answer");
|
||||
});
|
||||
|
|
|
@ -65,7 +65,7 @@ registerCleanupFunction(() => {
|
|||
function run_test() {
|
||||
prefs.setCharPref(
|
||||
"network.trr.uri",
|
||||
"https://foo.example.com:" + h2Port + "/doh"
|
||||
"https://foo.example.com:" + h2Port + "/esni-dns"
|
||||
);
|
||||
run_test_in_child("child_esni_dns_fetch1.js");
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
let h2Port;
|
||||
let prefs;
|
||||
|
||||
function setup() {
|
||||
let env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||
Ci.nsIEnvironment
|
||||
);
|
||||
h2Port = env.get("MOZHTTP2_PORT");
|
||||
Assert.notEqual(h2Port, null);
|
||||
Assert.notEqual(h2Port, "");
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
prefs.setBoolPref("network.security.esni.enabled", false);
|
||||
prefs.setBoolPref("network.http.spdy.enabled", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
|
||||
// the TRR server is on 127.0.0.1
|
||||
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
|
||||
|
||||
// make all native resolve calls "secretly" resolve localhost instead
|
||||
prefs.setBoolPref("network.dns.native-is-localhost", true);
|
||||
|
||||
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
|
||||
prefs.setIntPref("network.trr.mode", 2); // TRR first
|
||||
prefs.setBoolPref("network.trr.wait-for-portal", false);
|
||||
// don't confirm that TRR is working, just go!
|
||||
prefs.setCharPref("network.trr.confirmationNS", "skip");
|
||||
|
||||
// So we can change the pref without clearing the cache to check a pushed
|
||||
// record with a TRR path that fails.
|
||||
prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
|
||||
|
||||
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
|
||||
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
|
||||
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||
Ci.nsIX509CertDB
|
||||
);
|
||||
addCertFromFile(certdb, "../unit/http2-ca.pem", "CTu,u,u");
|
||||
}
|
||||
|
||||
setup();
|
||||
registerCleanupFunction(() => {
|
||||
prefs.clearUserPref("network.security.esni.enabled");
|
||||
prefs.clearUserPref("network.http.spdy.enabled");
|
||||
prefs.clearUserPref("network.http.spdy.enabled.http2");
|
||||
prefs.clearUserPref("network.dns.localDomains");
|
||||
prefs.clearUserPref("network.dns.native-is-localhost");
|
||||
prefs.clearUserPref("network.trr.mode");
|
||||
prefs.clearUserPref("network.trr.uri");
|
||||
prefs.clearUserPref("network.trr.credentials");
|
||||
prefs.clearUserPref("network.trr.wait-for-portal");
|
||||
prefs.clearUserPref("network.trr.allow-rfc1918");
|
||||
prefs.clearUserPref("network.trr.useGET");
|
||||
prefs.clearUserPref("network.trr.confirmationNS");
|
||||
prefs.clearUserPref("network.trr.bootstrapAddress");
|
||||
prefs.clearUserPref("network.trr.blacklist-duration");
|
||||
prefs.clearUserPref("network.trr.request-timeout");
|
||||
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
prefs.setCharPref(
|
||||
"network.trr.uri",
|
||||
"https://foo.example.com:" + h2Port + "/httpssvc"
|
||||
);
|
||||
run_test_in_child("../unit/test_trr_httpssvc.js");
|
||||
}
|
|
@ -59,7 +59,6 @@ support-files =
|
|||
!/netwerk/test/unit/test_original_sent_received_head.js
|
||||
!/netwerk/test/unit/test_alt-data_cross_process.js
|
||||
!/netwerk/test/unit/test_httpcancel.js
|
||||
!/netwerk/test/unit/test_trr_httpssvc.js
|
||||
child_cookie_header.js
|
||||
child_esni_dns_fetch1.js
|
||||
|
||||
|
@ -111,4 +110,3 @@ skip-if = true
|
|||
[test_alt-data_cross_process_wrap.js]
|
||||
[test_httpcancel_wrap.js]
|
||||
[test_esni_dns_fetch_wrap.js]
|
||||
[test_trr_httpssvc_wrap.js]
|
||||
|
|
|
@ -628,6 +628,7 @@ ra.decode = function (buf, offset) {
|
|||
ra.decode.bytes = 6
|
||||
return host
|
||||
}
|
||||
|
||||
ra.decode.bytes = 0
|
||||
|
||||
ra.encodingLength = function () {
|
||||
|
@ -1272,213 +1273,6 @@ rds.encodingLength = function (digest) {
|
|||
return 6 + Buffer.byteLength(digest.digest)
|
||||
}
|
||||
|
||||
const svcparam = exports.svcparam = {}
|
||||
|
||||
svcparam.keyToNumber = function(keyName) {
|
||||
switch (keyName.toLowerCase()) {
|
||||
case 'alpn' : return 1
|
||||
case 'no-default-alpn' : return 2
|
||||
case 'port' : return 3
|
||||
case 'ipv4hint' : return 4
|
||||
case 'esniconfig' : return 5
|
||||
case 'ipv6hint' : return 6
|
||||
case 'key65535' : return 65535
|
||||
}
|
||||
if (!keyName.startsWith('key')) {
|
||||
throw new Error(`Name must start with key: ${keyName}`);
|
||||
}
|
||||
|
||||
return Number.parseInt(keyName.substring(3));
|
||||
}
|
||||
|
||||
svcparam.numberToKeyName = function(number) {
|
||||
switch (number) {
|
||||
case 0 : return ''
|
||||
case 1 : return 'alpn'
|
||||
case 2 : return 'no-default-alpn'
|
||||
case 3 : return 'port'
|
||||
case 4 : return 'ipv4hint'
|
||||
case 5 : return 'esniconfig'
|
||||
case 6 : return 'ipv6hint'
|
||||
}
|
||||
|
||||
return `key${number}`;
|
||||
}
|
||||
|
||||
svcparam.encode = function(param, buf, offset) {
|
||||
if (!buf) buf = Buffer.allocUnsafe(svcparam.encodingLength(param))
|
||||
if (!offset) offset = 0
|
||||
|
||||
let key = param.key;
|
||||
if (typeof param.key !== 'number') {
|
||||
key = svcparam.keyToNumber(param.key);
|
||||
}
|
||||
|
||||
buf.writeUInt16BE(key || 0, offset)
|
||||
offset += 2;
|
||||
svcparam.encode.bytes = 2;
|
||||
|
||||
if (key == 1) { // alpn
|
||||
let len = param.value.length
|
||||
buf.writeUInt16BE(len || 0, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
buf.write(param.value, offset)
|
||||
offset += len;
|
||||
svcparam.encode.bytes += len;
|
||||
} else if (key == 2) { // no-default-alpn
|
||||
buf.writeUInt16BE(0, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
} else if (key == 3) { // port
|
||||
buf.writeUInt16BE(2, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
buf.writeUInt16BE(param.value || 0, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
} else if (key == 4) { //ipv4hint
|
||||
let val = param.value;
|
||||
if (!Array.isArray(val)) val = [val];
|
||||
buf.writeUInt16BE(val.length*4, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
|
||||
for (let host of val) {
|
||||
ip.toBuffer(host, buf, offset)
|
||||
offset += 4;
|
||||
svcparam.encode.bytes += 4;
|
||||
}
|
||||
} else if (key == 5) { //esniconfig
|
||||
// TODO: base64 presentation format
|
||||
buf.writeUInt16BE(param.value.length, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
buf.write(param.value, offset);
|
||||
offset += param.value.length;
|
||||
svcparam.encode.bytes += param.value.length;
|
||||
} else if (key == 6) { //ipv6hint
|
||||
let val = param.value;
|
||||
if (!Array.isArray(val)) val = [val];
|
||||
buf.writeUInt16BE(val.length*16, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
|
||||
for (let host of val) {
|
||||
ip.toBuffer(host, buf, offset)
|
||||
offset += 16;
|
||||
svcparam.encode.bytes += 16;
|
||||
}
|
||||
} else {
|
||||
// Unknown option
|
||||
buf.writeUInt16BE(param.value || 0, offset);
|
||||
offset += 2;
|
||||
svcparam.encode.bytes += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
svcparam.encode.bytes = 0;
|
||||
|
||||
svcparam.decode = function (buf, offset) {
|
||||
let param = {};
|
||||
let id = buf.readUInt16BE(offset);
|
||||
param.key = svcparam.numberToKeyName(id);
|
||||
offset += 2;
|
||||
svcparam.decode.bytes = 2;
|
||||
|
||||
let len = buf.readUInt16BE(offset);
|
||||
offset += 2;
|
||||
svcparam.decode.bytes += 2;
|
||||
|
||||
param.value = buf.toString('utf-8', offset, offset + len);
|
||||
offset += len;
|
||||
svcparam.decode.bytes += len;
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
svcparam.decode.bytes = 0;
|
||||
|
||||
svcparam.encodingLength = function (param) {
|
||||
// 2 bytes for type, 2 bytes for length, what's left for the value
|
||||
|
||||
switch (param.key) {
|
||||
case 'alpn' : return 4 + param.value.length
|
||||
case 'no-default-alpn' : return 4
|
||||
case 'port' : return 4 + 2
|
||||
case 'ipv4hint' : return 4+4 * (Array.isArray(param.value) ? param.value.length : 1)
|
||||
case 'esniconfig' : return 4 + param.value.length
|
||||
case 'ipv6hint' : return 4 + 16 * (Array.isArray(param.value) ? param.value.length : 1)
|
||||
case 'key65535' : return 4
|
||||
default: return 4 // unknown option
|
||||
}
|
||||
}
|
||||
|
||||
const rhttpssvc = exports.httpssvc = {}
|
||||
|
||||
rhttpssvc.encode = function(data, buf, offset) {
|
||||
if (!buf) buf = Buffer.allocUnsafe(rhttpssvc.encodingLength(data))
|
||||
if (!offset) offset = 0
|
||||
|
||||
buf.writeUInt16BE(rhttpssvc.encodingLength(data) - 2 , offset);
|
||||
offset += 2;
|
||||
|
||||
buf.writeUInt16BE(data.priority || 0, offset);
|
||||
rhttpssvc.encode.bytes = 4;
|
||||
offset += 2;
|
||||
name.encode(data.name, buf, offset);
|
||||
rhttpssvc.encode.bytes += name.encode.bytes;
|
||||
offset += name.encode.bytes;
|
||||
|
||||
if (data.priority == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let val of data.values) {
|
||||
svcparam.encode(val, buf, offset);
|
||||
offset += svcparam.encode.bytes;
|
||||
rhttpssvc.encode.bytes += svcparam.encode.bytes;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
rhttpssvc.encode.bytes = 0;
|
||||
|
||||
rhttpssvc.decode = function (buf, offset) {
|
||||
let rdlen = buf.readUInt16BE(offset);
|
||||
let oldOffset = offset;
|
||||
offset += 2;
|
||||
let record = {}
|
||||
record.priority = buf.readUInt16BE(offset);
|
||||
offset += 2;
|
||||
rhttpssvc.decode.bytes = 4;
|
||||
record.name = name.decode(buf, offset);
|
||||
offset += name.decode.bytes;
|
||||
rhttpssvc.decode.bytes += name.decode.bytes;
|
||||
|
||||
while (rdlen > rhttpssvc.decode.bytes - 2) {
|
||||
let rec1 = svcparam.decode(buf, offset);
|
||||
offset += svcparam.decode.bytes;
|
||||
rhttpssvc.decode.bytes += svcparam.decode.bytes;
|
||||
record.values.push(rec1);
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
rhttpssvc.decode.bytes = 0;
|
||||
|
||||
rhttpssvc.encodingLength = function (data) {
|
||||
let len =
|
||||
2 + // rdlen
|
||||
2 + // priority
|
||||
name.encodingLength(data.name);
|
||||
len += data.values.map(svcparam.encodingLength).reduce((acc, len) => acc + len, 0);
|
||||
return len;
|
||||
}
|
||||
|
||||
const renc = exports.record = function (type) {
|
||||
switch (type.toUpperCase()) {
|
||||
case 'A': return ra
|
||||
|
@ -1501,7 +1295,6 @@ const renc = exports.record = function (type) {
|
|||
case 'NSEC': return rnsec
|
||||
case 'NSEC3': return rnsec3
|
||||
case 'DS': return rds
|
||||
case 'HTTPSSVC': return rhttpssvc
|
||||
}
|
||||
return runknown
|
||||
}
|
||||
|
@ -1569,6 +1362,7 @@ answer.decode = function (buf, offset) {
|
|||
} else {
|
||||
const klass = buf.readUInt16BE(offset + 2)
|
||||
a.ttl = buf.readUInt32BE(offset + 4)
|
||||
|
||||
a.class = classes.toString(klass & NOT_FLUSH_MASK)
|
||||
a.flush = !!(klass & FLUSH_MASK)
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ exports.toString = function (type) {
|
|||
case 251: return 'IXFR'
|
||||
case 41: return 'OPT'
|
||||
case 255: return 'ANY'
|
||||
case 65345: return 'HTTPSSVC' // TODO
|
||||
}
|
||||
return 'UNKNOWN_' + type
|
||||
}
|
||||
|
@ -97,7 +96,6 @@ exports.toType = function (name) {
|
|||
case 'IXFR': return 251
|
||||
case 'OPT': return 41
|
||||
case 'ANY': return 255
|
||||
case 'HTTPSSVC': return 65345 // TODO
|
||||
case '*': return 255
|
||||
}
|
||||
if (name.toUpperCase().startsWith('UNKNOWN_')) return parseInt(name.slice(8))
|
||||
|
|
|
@ -712,34 +712,6 @@ function handleRequest(req, res) {
|
|||
});
|
||||
}
|
||||
|
||||
// for use with test_esni_dns_fetch.js
|
||||
if (packet.questions[0].type == "TXT") {
|
||||
answers.push({
|
||||
name: packet.questions[0].name,
|
||||
type: packet.questions[0].type,
|
||||
ttl: 55,
|
||||
class: "IN",
|
||||
flush: false,
|
||||
data: Buffer.from(
|
||||
"62586B67646D39705932556761584D6762586B676347467A63336476636D513D",
|
||||
"hex"
|
||||
),
|
||||
});
|
||||
} else if (packet.questions[0].type == "HTTPSSVC") {
|
||||
answers.push({
|
||||
name: packet.questions[0].name,
|
||||
type: packet.questions[0].type,
|
||||
ttl: 55,
|
||||
class: "IN",
|
||||
flush: false,
|
||||
data: {
|
||||
priority: 1,
|
||||
name: "some.domain.stuff.",
|
||||
values: [{ key: "esniconfig", value: "testytestystringstring" }],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (u.query.cnameloop) {
|
||||
answers.push({
|
||||
name: "cname.example.com",
|
||||
|
@ -821,78 +793,6 @@ function handleRequest(req, res) {
|
|||
}
|
||||
});
|
||||
return;
|
||||
} else if (u.pathname === "/httpssvc") {
|
||||
let payload = Buffer.from("");
|
||||
req.on("data", function receiveData(chunk) {
|
||||
payload = Buffer.concat([payload, chunk]);
|
||||
});
|
||||
req.on("end", function finishedData() {
|
||||
let packet = dnsPacket.decode(payload);
|
||||
let answers = [];
|
||||
answers.push({
|
||||
name: packet.questions[0].name,
|
||||
type: packet.questions[0].type,
|
||||
ttl: 55,
|
||||
class: "IN",
|
||||
flush: false,
|
||||
data: {
|
||||
priority: 1,
|
||||
name: "h3pool",
|
||||
values: [
|
||||
{ key: "alpn", value: "h2,h3" },
|
||||
{ key: "no-default-alpn" },
|
||||
{ key: "port", value: 8888 },
|
||||
{ key: "ipv4hint", value: "1.2.3.4" },
|
||||
{ key: "esniconfig", value: "123..." },
|
||||
{ key: "ipv6hint", value: "::1" },
|
||||
{ key: 30, value: "somelargestring" },
|
||||
],
|
||||
},
|
||||
});
|
||||
answers.push({
|
||||
name: packet.questions[0].name,
|
||||
type: packet.questions[0].type,
|
||||
ttl: 55,
|
||||
class: "IN",
|
||||
flush: false,
|
||||
data: {
|
||||
priority: 2,
|
||||
name: ".",
|
||||
values: [
|
||||
{ key: "alpn", value: "h2" },
|
||||
{ key: "ipv4hint", value: ["1.2.3.4", "5.6.7.8"] },
|
||||
{ key: "esniconfig", value: "abc..." },
|
||||
{ key: "ipv6hint", value: ["::1", "fe80::794f:6d2c:3d5e:7836"] },
|
||||
],
|
||||
},
|
||||
});
|
||||
answers.push({
|
||||
name: packet.questions[0].name,
|
||||
type: packet.questions[0].type,
|
||||
ttl: 55,
|
||||
class: "IN",
|
||||
flush: false,
|
||||
data: {
|
||||
priority: 3,
|
||||
name: "hello",
|
||||
values: [],
|
||||
},
|
||||
});
|
||||
let buf = dnsPacket.encode({
|
||||
type: "response",
|
||||
id: packet.id,
|
||||
flags: dnsPacket.RECURSION_DESIRED,
|
||||
questions: packet.questions,
|
||||
answers,
|
||||
});
|
||||
|
||||
res.setHeader("Content-Type", "application/dns-message");
|
||||
res.setHeader("Content-Length", buf.length);
|
||||
res.writeHead(200);
|
||||
res.write(buf);
|
||||
res.end("");
|
||||
});
|
||||
return;
|
||||
} else if (u.pathname === "/dns-cname-a") {
|
||||
// test23 asks for cname-a.example.com
|
||||
// this responds with a CNAME to here.example.com *and* an A record
|
||||
|
@ -936,6 +836,33 @@ function handleRequest(req, res) {
|
|||
// it's just meant to be this slow - the test doesn't care about the actual response
|
||||
return;
|
||||
}
|
||||
// for use with test_esni_dns_fetch.js
|
||||
else if (u.pathname === "/esni-dns") {
|
||||
content = Buffer.from(
|
||||
"0000" +
|
||||
"8180" +
|
||||
"0001" + // QDCOUNT
|
||||
"0001" + // ANCOUNT
|
||||
"00000000" + // NSCOUNT + ARCOUNT
|
||||
"055F65736E69076578616D706C6503636F6D00" + // _esni.example.com
|
||||
"00100001" + // question type (TXT) + question class (IN)
|
||||
"C00C" + // name pointer to .example.com
|
||||
"0010" + // type (TXT)
|
||||
"0001" + // class
|
||||
"00000037" + // TTL
|
||||
"0021" + // RDLENGTH
|
||||
"2062586B67646D39705932556761584D6762586B676347467A63336476636D513D", // esni keys.
|
||||
"hex"
|
||||
);
|
||||
|
||||
res.setHeader("Content-Type", "application/dns-message");
|
||||
res.setHeader("Content-Length", content.length);
|
||||
res.writeHead(200);
|
||||
res.write(content);
|
||||
res.end("");
|
||||
return;
|
||||
}
|
||||
|
||||
// for use with test_esni_dns_fetch.js
|
||||
else if (u.pathname === "/esni-dns-push") {
|
||||
// _esni_push.example.com has A entry 127.0.0.1
|
||||
|
|
Загрузка…
Ссылка в новой задаче