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:
Dorel Luca 2020-05-04 20:54:15 +03:00
Родитель 9d800df7de
Коммит 8278ad20d7
30 изменённых файлов: 192 добавлений и 1605 удалений

Просмотреть файл

@ -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__

23
netwerk/dns/PDNSParams.h Normal file
Просмотреть файл

@ -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