Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp
Warning:line 264, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_netwerk_dns0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/dns -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/dns -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/dns -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_netwerk_dns0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim:set ts=4 sw=2 sts=2 et cin: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "DNS.h"
8#include "DNSUtils.h"
9#include "nsCharSeparatedTokenizer.h"
10#include "nsContentUtils.h"
11#include "nsHttpHandler.h"
12#include "nsHttpChannel.h"
13#include "nsHostResolver.h"
14#include "nsIHttpChannel.h"
15#include "nsIHttpChannelInternal.h"
16#include "nsIIOService.h"
17#include "nsIInputStream.h"
18#include "nsIObliviousHttp.h"
19#include "nsIOService.h"
20#include "nsISupports.h"
21#include "nsISupportsUtils.h"
22#include "nsITimedChannel.h"
23#include "nsIUploadChannel2.h"
24#include "nsIURIMutator.h"
25#include "nsNetUtil.h"
26#include "nsQueryObject.h"
27#include "nsStringStream.h"
28#include "nsThreadUtils.h"
29#include "nsURLHelper.h"
30#include "ObliviousHttpChannel.h"
31#include "TRR.h"
32#include "TRRService.h"
33#include "TRRServiceChannel.h"
34#include "TRRLoadInfo.h"
35
36#include "mozilla/Base64.h"
37#include "mozilla/DebugOnly.h"
38#include "mozilla/Logging.h"
39#include "mozilla/Preferences.h"
40#include "mozilla/StaticPrefs_network.h"
41#include "mozilla/Telemetry.h"
42#include "mozilla/TimeStamp.h"
43#include "mozilla/Tokenizer.h"
44#include "mozilla/UniquePtr.h"
45// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
46#include "DNSLogging.h"
47#include "mozilla/glean/GleanMetrics.h"
48
49namespace mozilla {
50namespace net {
51
52NS_IMPL_ISUPPORTS(TRR, nsIHttpPushListener, nsIInterfaceRequestor,MozExternalRefCountType TRR::AddRef(void) { static_assert(!std
::is_destructible_v<TRR>, "Reference-counted class " "TRR"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
53; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 53; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef
((this), (count), ("TRR"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType TRR::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 53
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 53; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); const char* const nametmp = "TRR"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult TRR::QueryInterface(const nsIID
& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(5 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<TRR, nsIHttpPushListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpPushListener*>((TRR*)0x1000
)) - reinterpret_cast<char*>((TRR*)0x1000))}, {&mozilla
::detail::kImplementedIID<TRR, nsIInterfaceRequestor>, int32_t
( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIRunnable
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRunnable
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIHttpPushListener*>((TRR*)0x1000))
) - reinterpret_cast<char*>((TRR*)0x1000))}, { nullptr,
0 } } ; static_assert((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
53 nsIStreamListener, nsIRunnable, nsITimerCallback)MozExternalRefCountType TRR::AddRef(void) { static_assert(!std
::is_destructible_v<TRR>, "Reference-counted class " "TRR"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
53; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 53; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef
((this), (count), ("TRR"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType TRR::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 53
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 53; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); const char* const nametmp = "TRR"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult TRR::QueryInterface(const nsIID
& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 53); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(5 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<TRR, nsIHttpPushListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpPushListener*>((TRR*)0x1000
)) - reinterpret_cast<char*>((TRR*)0x1000))}, {&mozilla
::detail::kImplementedIID<TRR, nsIInterfaceRequestor>, int32_t
( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIRunnable
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRunnable
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIHttpPushListener*>((TRR*)0x1000))
) - reinterpret_cast<char*>((TRR*)0x1000))}, { nullptr,
0 } } ; static_assert((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
54
55// when firing off a normal A or AAAA query
56TRR::TRR(AHostResolver* aResolver, nsHostRecord* aRec, enum TrrType aType)
57 : mozilla::Runnable("TRR"),
58 mRec(aRec),
59 mHostResolver(aResolver),
60 mType(aType),
61 mOriginSuffix(aRec->originSuffix) {
62 mHost = aRec->host;
63 mPB = aRec->pb;
64 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 65); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 65; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
65 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 65); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 65; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
66}
67
68// when following CNAMEs
69TRR::TRR(AHostResolver* aResolver, nsHostRecord* aRec, nsCString& aHost,
70 enum TrrType& aType, unsigned int aLoopCount, bool aPB)
71 : mozilla::Runnable("TRR"),
72 mHost(aHost),
73 mRec(aRec),
74 mHostResolver(aResolver),
75 mType(aType),
76 mPB(aPB),
77 mCnameLoop(aLoopCount),
78 mOriginSuffix(aRec ? aRec->originSuffix : ""_ns) {
79 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 80); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 80; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
80 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 80); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 80; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
81}
82
83// used on push
84TRR::TRR(AHostResolver* aResolver, bool aPB)
85 : mozilla::Runnable("TRR"), mHostResolver(aResolver), mPB(aPB) {
86 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 87); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 87; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
87 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 87); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 87; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
88}
89
90// to verify a domain
91TRR::TRR(AHostResolver* aResolver, nsACString& aHost, enum TrrType aType,
92 const nsACString& aOriginSuffix, bool aPB, bool aUseFreshConnection)
93 : mozilla::Runnable("TRR"),
94 mHost(aHost),
95 mRec(nullptr),
96 mHostResolver(aResolver),
97 mType(aType),
98 mPB(aPB),
99 mOriginSuffix(aOriginSuffix),
100 mUseFreshConnection(aUseFreshConnection) {
101 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 102); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 102; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
102 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 102); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 102; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
103}
104
105void TRR::HandleTimeout() {
106 mTimeout = nullptr;
107 RecordReason(TRRSkippedReason::TRR_TIMEOUT);
108 Cancel(NS_ERROR_NET_TIMEOUT_EXTERNAL);
109}
110
111NS_IMETHODIMPnsresult
112TRR::Notify(nsITimer* aTimer) {
113 if (aTimer == mTimeout) {
114 HandleTimeout();
115 } else {
116 MOZ_CRASH("Unknown timer")do { do { } while (false); MOZ_ReportCrash("" "Unknown timer"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 116); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown timer" ")"
); do { *((volatile int*)__null) = 116; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
117 }
118
119 return NS_OK;
120}
121
122NS_IMETHODIMPnsresult
123TRR::Run() {
124 MOZ_ASSERT_IF(XRE_IsParentProcess() && TRRService::Get(),do { if (XRE_IsParentProcess() && TRRService::Get()) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
")"); do { *((volatile int*)__null) = 125; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
125 NS_IsMainThread() || TRRService::Get()->IsOnTRRThread())do { if (XRE_IsParentProcess() && TRRService::Get()) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
")"); do { *((volatile int*)__null) = 125; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
126 MOZ_ASSERT_IF(XRE_IsSocketProcess(), NS_IsMainThread())do { if (XRE_IsSocketProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(NS_IsMainThread(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 126; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
127
128 if ((TRRService::Get() == nullptr) || NS_FAILED(SendHTTPRequest())((bool)(__builtin_expect(!!(NS_FAILED_impl(SendHTTPRequest())
), 0)))
) {
129 RecordReason(TRRSkippedReason::TRR_SEND_FAILED);
130 FailData(NS_ERROR_FAILURE);
131 // The dtor will now be run
132 }
133 return NS_OK;
134}
135
136DNSPacket* TRR::GetOrCreateDNSPacket() {
137 if (!mPacket) {
138 mPacket = MakeUnique<DNSPacket>();
139 }
140
141 return mPacket.get();
142}
143
144nsresult TRR::CreateQueryURI(nsIURI** aOutURI) {
145 nsAutoCString uri;
146 nsCOMPtr<nsIURI> dnsURI;
147 if (UseDefaultServer()) {
148 TRRService::Get()->GetURI(uri);
149 } else {
150 uri = mRec->mTrrServer;
151 }
152
153 nsresult rv = NS_NewURI(getter_AddRefs(dnsURI), uri);
154 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
155 RecordReason(TRRSkippedReason::TRR_BAD_URL);
156 return rv;
157 }
158
159 dnsURI.forget(aOutURI);
160 return NS_OK;
161}
162
163bool TRR::MaybeBlockRequest() {
164 if (((mType == TRRTYPE_A) || (mType == TRRTYPE_AAAA)) &&
165 mRec->mEffectiveTRRMode != nsIRequest::TRR_ONLY_MODE) {
166 // let NS resolves skip the blocklist check
167 // we also don't check the blocklist for TRR only requests
168 MOZ_ASSERT(mRec)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRec)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mRec))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mRec", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRec" ")"); do
{ *((volatile int*)__null) = 168; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
169
170 // If TRRService isn't enabled anymore for the req, don't do TRR.
171 if (!TRRService::Get()->Enabled(mRec->mEffectiveTRRMode)) {
172 RecordReason(TRRSkippedReason::TRR_MODE_NOT_ENABLED);
173 return true;
174 }
175
176 if (!StaticPrefs::network_trr_strict_native_fallback() &&
177 UseDefaultServer() &&
178 TRRService::Get()->IsTemporarilyBlocked(mHost, mOriginSuffix, mPB,
179 true)) {
180 if (mType == TRRTYPE_A) {
181 // count only blocklist for A records to avoid double counts
182 Telemetry::Accumulate(Telemetry::DNS_TRR_BLACKLISTED3,
183 TRRService::ProviderKey(), true);
184 }
185
186 RecordReason(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY);
187 // not really an error but no TRR is issued
188 return true;
189 }
190
191 if (TRRService::Get()->IsExcludedFromTRR(mHost)) {
192 RecordReason(TRRSkippedReason::TRR_EXCLUDED);
193 return true;
194 }
195
196 if (UseDefaultServer() && (mType == TRRTYPE_A)) {
197 Telemetry::Accumulate(Telemetry::DNS_TRR_BLACKLISTED3,
198 TRRService::ProviderKey(), false);
199 }
200 }
201
202 return false;
203}
204
205nsresult TRR::SendHTTPRequest() {
206 // This is essentially the "run" method - created from nsHostResolver
207 if (mCancelled) {
208 return NS_ERROR_FAILURE;
209 }
210
211 if ((mType != TRRTYPE_A) && (mType != TRRTYPE_AAAA) &&
212 (mType != TRRTYPE_NS) && (mType != TRRTYPE_TXT) &&
213 (mType != TRRTYPE_HTTPSSVC)) {
214 // limit the calling interface because nsHostResolver has explicit slots for
215 // these types
216 return NS_ERROR_FAILURE;
217 }
218
219 if (MaybeBlockRequest()) {
220 return NS_ERROR_UNKNOWN_HOST;
221 }
222
223 LOG(("TRR::SendHTTPRequest resolve %s type %u\n", mHost.get(), mType))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest resolve %s type %u\n", mHost.get(), mType
); } } while (0)
;
224
225 nsAutoCString body;
226 bool disableECS = StaticPrefs::network_trr_disable_ECS();
227 nsresult rv =
228 GetOrCreateDNSPacket()->EncodeRequest(body, mHost, mType, disableECS);
229 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
230 HandleEncodeError(rv);
231 return rv;
232 }
233
234 bool useGet = StaticPrefs::network_trr_useGET();
235 nsCOMPtr<nsIURI> dnsURI;
236 rv = CreateQueryURI(getter_AddRefs(dnsURI));
237 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
238 LOG(("TRR:SendHTTPRequest: NewURI failed!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:SendHTTPRequest: NewURI failed!\n"); } } while (0)
;
239 return rv;
240 }
241
242 if (useGet) {
243 /* For GET requests, the outgoing packet needs to be Base64url-encoded and
244 then appended to the end of the URI. */
245 nsAutoCString encoded;
246 rv = Base64URLEncode(body.Length(),
247 reinterpret_cast<const unsigned char*>(body.get()),
248 Base64URLEncodePaddingPolicy::Omit, encoded);
249 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 249); return rv; } } while (false)
;
250
251 nsAutoCString query;
252 rv = dnsURI->GetQuery(query);
253 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
254 return rv;
255 }
256
257 if (query.IsEmpty()) {
258 query.Assign("?dns="_ns);
259 } else {
260 query.Append("&dns="_ns);
261 }
262 query.Append(encoded);
263
264 rv = NS_MutateURI(dnsURI).SetQuery(query).Finalize(dnsURI);
Value stored to 'rv' is never read
265 LOG(("TRR::SendHTTPRequest GET dns=%s\n", body.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest GET dns=%s\n", body.get()); } } while
(0)
;
266 }
267
268 nsCOMPtr<nsIChannel> channel;
269 bool useOHTTP = StaticPrefs::network_trr_use_ohttp();
270 if (useOHTTP) {
271 nsCOMPtr<nsIObliviousHttpService> ohttpService(
272 do_GetService("@mozilla.org/network/oblivious-http-service;1"));
273 if (!ohttpService) {
274 return NS_ERROR_FAILURE;
275 }
276 nsCOMPtr<nsIURI> relayURI;
277 nsTArray<uint8_t> encodedConfig;
278 rv = ohttpService->GetTRRSettings(getter_AddRefs(relayURI), encodedConfig);
279 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
280 return rv;
281 }
282 if (!relayURI) {
283 return NS_ERROR_FAILURE;
284 }
285 rv = ohttpService->NewChannel(relayURI, dnsURI, encodedConfig,
286 getter_AddRefs(channel));
287 } else {
288 rv = DNSUtils::CreateChannelHelper(dnsURI, getter_AddRefs(channel));
289 }
290 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !channel) {
291 LOG(("TRR:SendHTTPRequest: NewChannel failed!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:SendHTTPRequest: NewChannel failed!\n"); } } while (0)
;
292 return rv;
293 }
294
295 auto loadFlags = nsIRequest::LOAD_ANONYMOUS | nsIRequest::INHIBIT_CACHING |
296 nsIRequest::LOAD_BYPASS_CACHE |
297 nsIChannel::LOAD_BYPASS_URL_CLASSIFIER;
298 if (mUseFreshConnection) {
299 // Causes TRRServiceChannel to tell the connection manager
300 // to clear out any connection with the current conn info.
301 loadFlags |= nsIRequest::LOAD_FRESH_CONNECTION;
302 }
303 channel->SetLoadFlags(loadFlags);
304 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 304); return rv; } } while (false)
;
305
306 rv = channel->SetNotificationCallbacks(this);
307 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 307); return rv; } } while (false)
;
308
309 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
310 if (!httpChannel) {
311 return NS_ERROR_UNEXPECTED;
312 }
313
314 // This connection should not use TRR
315 rv = httpChannel->SetTRRMode(nsIRequest::TRR_DISABLED_MODE);
316 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 316); return rv; } } while (false)
;
317
318 nsCString contentType(ContentType());
319 rv = httpChannel->SetRequestHeader("Accept"_ns, contentType, false);
320 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 320); return rv; } } while (false)
;
321
322 nsAutoCString cred;
323 if (UseDefaultServer()) {
324 TRRService::Get()->GetCredentials(cred);
325 }
326 if (!cred.IsEmpty()) {
327 rv = httpChannel->SetRequestHeader("Authorization"_ns, cred, false);
328 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 328); return rv; } } while (false)
;
329 }
330
331 nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(channel);
332 if (!internalChannel) {
333 return NS_ERROR_UNEXPECTED;
334 }
335
336 // setting a small stream window means the h2 stack won't pipeline a window
337 // update with each HEADERS or reply to a DATA with a WINDOW UPDATE
338 rv = internalChannel->SetInitialRwin(127 * 1024);
339 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 339); return rv; } } while (false)
;
340 rv = internalChannel->SetIsTRRServiceChannel(true);
341 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 341); return rv; } } while (false)
;
342
343 if (UseDefaultServer() && StaticPrefs::network_trr_async_connInfo()) {
344 RefPtr<nsHttpConnectionInfo> trrConnInfo =
345 TRRService::Get()->TRRConnectionInfo();
346 if (trrConnInfo) {
347 nsAutoCString host;
348 dnsURI->GetHost(host);
349 if (host.Equals(trrConnInfo->GetOrigin())) {
350 internalChannel->SetConnectionInfo(trrConnInfo);
351 LOG(("TRR::SendHTTPRequest use conn info:%s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest use conn info:%s\n", trrConnInfo->
HashKey().get()); } } while (0)
352 trrConnInfo->HashKey().get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest use conn info:%s\n", trrConnInfo->
HashKey().get()); } } while (0)
;
353 } else {
354 MOZ_DIAGNOSTIC_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 354); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
")"); do { *((volatile int*)__null) = 354; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
355 }
356 } else {
357 TRRService::Get()->InitTRRConnectionInfo();
358 }
359 }
360
361 if (useGet) {
362 rv = httpChannel->SetRequestMethod("GET"_ns);
363 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 363); return rv; } } while (false)
;
364 } else {
365 nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(httpChannel);
366 if (!uploadChannel) {
367 return NS_ERROR_UNEXPECTED;
368 }
369 uint32_t streamLength = body.Length();
370 nsCOMPtr<nsIInputStream> uploadStream;
371 rv =
372 NS_NewCStringInputStream(getter_AddRefs(uploadStream), std::move(body));
373 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 373); return rv; } } while (false)
;
374
375 rv = uploadChannel->ExplicitSetUploadStream(uploadStream, contentType,
376 streamLength, "POST"_ns, false);
377 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 377); return rv; } } while (false)
;
378 }
379
380 rv = SetupTRRServiceChannelInternal(httpChannel, useGet, contentType);
381 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
382 return rv;
383 }
384
385 rv = httpChannel->AsyncOpen(this);
386 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
387 return rv;
388 }
389
390 // If the asyncOpen succeeded we can say that we actually attempted to
391 // use the TRR connection.
392 RefPtr<AddrHostRecord> addrRec = do_QueryObject(mRec);
393 if (addrRec) {
394 addrRec->mResolverType = ResolverType();
395 }
396
397 NS_NewTimerWithCallback(
398 getter_AddRefs(mTimeout), this,
399 mTimeoutMs ? mTimeoutMs : TRRService::Get()->GetRequestTimeout(),
400 nsITimer::TYPE_ONE_SHOT);
401
402 mChannel = channel;
403 return NS_OK;
404}
405
406// static
407nsresult TRR::SetupTRRServiceChannelInternal(nsIHttpChannel* aChannel,
408 bool aUseGet,
409 const nsACString& aContentType) {
410 nsCOMPtr<nsIHttpChannel> httpChannel = aChannel;
411 MOZ_ASSERT(httpChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(httpChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(httpChannel))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("httpChannel", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpChannel"
")"); do { *((volatile int*)__null) = 411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
412
413 nsresult rv = NS_OK;
414 if (!aUseGet) {
415 rv =
416 httpChannel->SetRequestHeader("Cache-Control"_ns, "no-store"_ns, false);
417 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 417); return rv; } } while (false)
;
418 }
419
420 // Sanitize the request by removing the Accept-Language header so we minimize
421 // the amount of fingerprintable information we send to the server.
422 if (!StaticPrefs::network_trr_send_accept_language_headers()) {
423 rv = httpChannel->SetRequestHeader("Accept-Language"_ns, ""_ns, false);
424 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 424); return rv; } } while (false)
;
425 }
426
427 // Sanitize the request by removing the User-Agent
428 if (!StaticPrefs::network_trr_send_user_agent_headers()) {
429 rv = httpChannel->SetRequestHeader("User-Agent"_ns, ""_ns, false);
430 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 430); return rv; } } while (false)
;
431 }
432
433 if (StaticPrefs::network_trr_send_empty_accept_encoding_headers()) {
434 rv = httpChannel->SetEmptyRequestHeader("Accept-Encoding"_ns);
435 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 435); return rv; } } while (false)
;
436 }
437
438 // set the *default* response content type
439 if (NS_FAILED(httpChannel->SetContentType(aContentType))((bool)(__builtin_expect(!!(NS_FAILED_impl(httpChannel->SetContentType
(aContentType))), 0)))
) {
440 LOG(("TRR::SetupTRRServiceChannelInternal: couldn't set content-type!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SetupTRRServiceChannelInternal: couldn't set content-type!\n"
); } } while (0)
;
441 }
442
443 nsCOMPtr<nsITimedChannel> timedChan(do_QueryInterface(httpChannel));
444 if (timedChan) {
445 timedChan->SetTimingEnabled(true);
446 }
447
448 return NS_OK;
449}
450
451NS_IMETHODIMPnsresult
452TRR::GetInterface(const nsIID& iid, void** result) {
453 if (!iid.Equals(NS_GET_IID(nsIHttpPushListener)(nsIHttpPushListener::COMTypeInfo<nsIHttpPushListener, void
>::kIID)
)) {
454 return NS_ERROR_NO_INTERFACE;
455 }
456
457 nsCOMPtr<nsIHttpPushListener> copy(this);
458 *result = copy.forget().take();
459 return NS_OK;
460}
461
462nsresult TRR::DohDecodeQuery(const nsCString& query, nsCString& host,
463 enum TrrType& type) {
464 FallibleTArray<uint8_t> binary;
465 bool found_dns = false;
466 LOG(("TRR::DohDecodeQuery %s!\n", query.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery %s!\n", query.get()); } } while (0)
;
467
468 // extract "dns=" from the query string
469 nsAutoCString data;
470 for (const nsACString& token :
471 nsCCharSeparatedTokenizer(query, '&').ToRange()) {
472 nsDependentCSubstring dns = Substring(token, 0, 4);
473 nsAutoCString check(dns);
474 if (check.Equals("dns=")) {
475 nsDependentCSubstring q = Substring(token, 4, -1);
476 data = q;
477 found_dns = true;
478 break;
479 }
480 }
481 if (!found_dns) {
482 LOG(("TRR::DohDecodeQuery no dns= in pushed URI query string\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery no dns= in pushed URI query string\n")
; } } while (0)
;
483 return NS_ERROR_ILLEGAL_VALUE;
484 }
485
486 nsresult rv =
487 Base64URLDecode(data, Base64URLDecodePaddingPolicy::Ignore, binary);
488 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 488); return rv; } } while (false)
;
489 uint32_t avail = binary.Length();
490 if (avail < 12) {
491 return NS_ERROR_FAILURE;
492 }
493 // check the query bit and the opcode
494 if ((binary[2] & 0xf8) != 0) {
495 return NS_ERROR_FAILURE;
496 }
497 uint32_t qdcount = (binary[4] << 8) + binary[5];
498 if (!qdcount) {
499 return NS_ERROR_FAILURE;
500 }
501
502 uint32_t index = 12;
503 uint32_t length = 0;
504 host.Truncate();
505 do {
506 if (avail < (index + 1)) {
507 return NS_ERROR_UNEXPECTED;
508 }
509
510 length = binary[index];
511 if (length) {
512 if (host.Length()) {
513 host.Append(".");
514 }
515 if (avail < (index + 1 + length)) {
516 return NS_ERROR_UNEXPECTED;
517 }
518 host.Append((const char*)(&binary[0]) + index + 1, length);
519 }
520 index += 1 + length; // skip length byte + label
521 } while (length);
522
523 LOG(("TRR::DohDecodeQuery host %s\n", host.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery host %s\n", host.get()); } } while (0)
;
524
525 if (avail < (index + 2)) {
526 return NS_ERROR_UNEXPECTED;
527 }
528 uint16_t i16 = 0;
529 i16 += binary[index] << 8;
530 i16 += binary[index + 1];
531 type = (enum TrrType)i16;
532
533 LOG(("TRR::DohDecodeQuery type %d\n", (int)type))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery type %d\n", (int)type); } } while (0)
;
534
535 return NS_OK;
536}
537
538nsresult TRR::ReceivePush(nsIHttpChannel* pushed, nsHostRecord* pushedRec) {
539 if (!mHostResolver) {
540 return NS_ERROR_UNEXPECTED;
541 }
542
543 LOG(("TRR::ReceivePush: PUSH incoming!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::ReceivePush: PUSH incoming!\n"); } } while (0)
;
544
545 nsCOMPtr<nsIURI> uri;
546 pushed->GetURI(getter_AddRefs(uri));
547 nsAutoCString query;
548 if (uri) {
549 uri->GetQuery(query);
550 }
551
552 if (NS_FAILED(DohDecodeQuery(query, mHost, mType))((bool)(__builtin_expect(!!(NS_FAILED_impl(DohDecodeQuery(query
, mHost, mType))), 0)))
||
553 HostIsIPLiteral(mHost)) { // literal
554 LOG(("TRR::ReceivePush failed to decode %s\n", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::ReceivePush failed to decode %s\n", mHost.get()); } }
while (0)
;
555 return NS_ERROR_UNEXPECTED;
556 }
557
558 if ((mType != TRRTYPE_A) && (mType != TRRTYPE_AAAA) &&
559 (mType != TRRTYPE_TXT) && (mType != TRRTYPE_HTTPSSVC)) {
560 LOG(("TRR::ReceivePush unknown type %d\n", mType))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::ReceivePush unknown type %d\n", mType); } } while (0)
;
561 return NS_ERROR_UNEXPECTED;
562 }
563
564 if (TRRService::Get()->IsExcludedFromTRR(mHost)) {
565 return NS_ERROR_FAILURE;
566 }
567
568 uint32_t type = nsIDNSService::RESOLVE_TYPE_DEFAULT;
569 if (mType == TRRTYPE_TXT) {
570 type = nsIDNSService::RESOLVE_TYPE_TXT;
571 } else if (mType == TRRTYPE_HTTPSSVC) {
572 type = nsIDNSService::RESOLVE_TYPE_HTTPSSVC;
573 }
574
575 RefPtr<nsHostRecord> hostRecord;
576 nsresult rv;
577 rv = mHostResolver->GetHostRecord(
578 mHost, ""_ns, type, pushedRec->flags, pushedRec->af, pushedRec->pb,
579 pushedRec->originSuffix, getter_AddRefs(hostRecord));
580 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
581 return rv;
582 }
583
584 // Since we don't ever call nsHostResolver::NameLookup for this record,
585 // we need to copy the trr mode from the previous record
586 if (hostRecord->mEffectiveTRRMode == nsIRequest::TRR_DEFAULT_MODE) {
587 hostRecord->mEffectiveTRRMode =
588 static_cast<nsIRequest::TRRMode>(pushedRec->mEffectiveTRRMode);
589 }
590
591 rv = mHostResolver->TrrLookup_unlocked(hostRecord, this);
592 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
593 return rv;
594 }
595
596 rv = pushed->AsyncOpen(this);
597 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
598 return rv;
599 }
600
601 // OK!
602 mChannel = pushed;
603 mRec.swap(hostRecord);
604
605 return NS_OK;
606}
607
608NS_IMETHODIMPnsresult
609TRR::OnPush(nsIHttpChannel* associated, nsIHttpChannel* pushed) {
610 LOG(("TRR::OnPush entry\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::OnPush entry\n"); } } while (0)
;
611 MOZ_ASSERT(associated == mChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(associated == mChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(associated == mChannel))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("associated == mChannel"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "associated == mChannel"
")"); do { *((volatile int*)__null) = 611; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
612 if (!mRec) {
613 return NS_ERROR_FAILURE;
614 }
615 if (!UseDefaultServer()) {
616 return NS_ERROR_FAILURE;
617 }
618
619 RefPtr<TRR> trr = new TRR(mHostResolver, mPB);
620 trr->SetPurpose(mPurpose);
621 return trr->ReceivePush(pushed, mRec);
622}
623
624NS_IMETHODIMPnsresult
625TRR::OnStartRequest(nsIRequest* aRequest) {
626 LOG(("TRR::OnStartRequest %p %s %d\n", this, mHost.get(), mType))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::OnStartRequest %p %s %d\n", this, mHost.get(), mType)
; } } while (0)
;
627
628 nsresult status = NS_OK;
629 aRequest->GetStatus(&status);
630
631 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
632 if (gIOService->InSleepMode()) {
633 RecordReason(TRRSkippedReason::TRR_SYSTEM_SLEEP_MODE);
634 } else if (NS_IsOffline()) {
635 RecordReason(TRRSkippedReason::TRR_BROWSER_IS_OFFLINE);
636 }
637
638 switch (status) {
639 case NS_ERROR_UNKNOWN_HOST:
640 RecordReason(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL);
641 break;
642 case NS_ERROR_OFFLINE:
643 RecordReason(TRRSkippedReason::TRR_BROWSER_IS_OFFLINE);
644 break;
645 case NS_ERROR_NET_RESET:
646 RecordReason(TRRSkippedReason::TRR_NET_RESET);
647 break;
648 case NS_ERROR_NET_TIMEOUT:
649 case NS_ERROR_NET_TIMEOUT_EXTERNAL:
650 RecordReason(TRRSkippedReason::TRR_NET_TIMEOUT);
651 break;
652 case NS_ERROR_PROXY_CONNECTION_REFUSED:
653 RecordReason(TRRSkippedReason::TRR_NET_REFUSED);
654 break;
655 case NS_ERROR_NET_INTERRUPT:
656 RecordReason(TRRSkippedReason::TRR_NET_INTERRUPT);
657 break;
658 case NS_ERROR_NET_INADEQUATE_SECURITY:
659 RecordReason(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY);
660 break;
661 default:
662 RecordReason(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE);
663 }
664 }
665
666 return NS_OK;
667}
668
669void TRR::SaveAdditionalRecords(
670 const nsClassHashtable<nsCStringHashKey, DOHresp>& aRecords) {
671 if (!mRec) {
672 return;
673 }
674 nsresult rv;
675 for (const auto& recordEntry : aRecords) {
676 if (!recordEntry.GetData() || recordEntry.GetData()->mAddresses.IsEmpty()) {
677 // no point in adding empty records.
678 continue;
679 }
680 // If IPv6 is disabled don't add anything else than IPv4.
681 if (StaticPrefs::network_dns_disableIPv6() &&
682 std::find_if(recordEntry.GetData()->mAddresses.begin(),
683 recordEntry.GetData()->mAddresses.end(),
684 [](const NetAddr& addr) { return !addr.IsIPAddrV4(); }) !=
685 recordEntry.GetData()->mAddresses.end()) {
686 continue;
687 }
688 RefPtr<nsHostRecord> hostRecord;
689 rv = mHostResolver->GetHostRecord(
690 recordEntry.GetKey(), EmptyCString(),
691 nsIDNSService::RESOLVE_TYPE_DEFAULT, mRec->flags, AF_UNSPEC0, mRec->pb,
692 mRec->originSuffix, getter_AddRefs(hostRecord));
693 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
694 LOG(("Failed to get host record for additional record %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Failed to get host record for additional record %s", nsCString
(recordEntry.GetKey()).get()); } } while (0)
695 nsCString(recordEntry.GetKey()).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Failed to get host record for additional record %s", nsCString
(recordEntry.GetKey()).get()); } } while (0)
;
696 continue;
697 }
698 RefPtr<AddrInfo> ai(
699 new AddrInfo(recordEntry.GetKey(), ResolverType(), TRRTYPE_A,
700 std::move(recordEntry.GetData()->mAddresses),
701 recordEntry.GetData()->mTtl));
702 mHostResolver->MaybeRenewHostRecord(hostRecord);
703
704 // Since we're not actually calling NameLookup for this record, we need
705 // to set these fields to avoid assertions in CompleteLookup.
706 // This is quite hacky, and should be fixed.
707 hostRecord->Reset();
708 hostRecord->mResolving++;
709 hostRecord->mEffectiveTRRMode =
710 static_cast<nsIRequest::TRRMode>(mRec->mEffectiveTRRMode);
711 LOG(("Completing lookup for additional: %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Completing lookup for additional: %s", nsCString(recordEntry
.GetKey()).get()); } } while (0)
712 nsCString(recordEntry.GetKey()).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Completing lookup for additional: %s", nsCString(recordEntry
.GetKey()).get()); } } while (0)
;
713 (void)mHostResolver->CompleteLookup(hostRecord, NS_OK, ai, mPB,
714 mOriginSuffix, TRRSkippedReason::TRR_OK,
715 this);
716 }
717}
718
719void TRR::StoreIPHintAsDNSRecord(const struct SVCB& aSVCBRecord) {
720 LOG(("TRR::StoreIPHintAsDNSRecord [%p] [%s]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::StoreIPHintAsDNSRecord [%p] [%s]", this, aSVCBRecord.
mSvcDomainName.get()); } } while (0)
721 aSVCBRecord.mSvcDomainName.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::StoreIPHintAsDNSRecord [%p] [%s]", this, aSVCBRecord.
mSvcDomainName.get()); } } while (0)
;
722 CopyableTArray<NetAddr> addresses;
723 aSVCBRecord.GetIPHints(addresses);
724
725 if (StaticPrefs::network_dns_disableIPv6()) {
726 addresses.RemoveElementsBy(
727 [](const NetAddr& addr) { return !addr.IsIPAddrV4(); });
728 }
729
730 if (addresses.IsEmpty()) {
731 return;
732 }
733
734 RefPtr<nsHostRecord> hostRecord;
735 nsresult rv = mHostResolver->GetHostRecord(
736 aSVCBRecord.mSvcDomainName, EmptyCString(),
737 nsIDNSService::RESOLVE_TYPE_DEFAULT,
738 mRec->flags | nsIDNSService::RESOLVE_IP_HINT, AF_UNSPEC0, mRec->pb,
739 mRec->originSuffix, getter_AddRefs(hostRecord));
740 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
741 LOG(("Failed to get host record"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Failed to get host record"); } } while (0)
;
742 return;
743 }
744
745 mHostResolver->MaybeRenewHostRecord(hostRecord);
746
747 RefPtr<AddrInfo> ai(new AddrInfo(aSVCBRecord.mSvcDomainName, ResolverType(),
748 TRRTYPE_A, std::move(addresses), mTTL));
749
750 // Since we're not actually calling NameLookup for this record, we need
751 // to set these fields to avoid assertions in CompleteLookup.
752 // This is quite hacky, and should be fixed.
753 hostRecord->mResolving++;
754 hostRecord->mEffectiveTRRMode =
755 static_cast<nsIRequest::TRRMode>(mRec->mEffectiveTRRMode);
756 (void)mHostResolver->CompleteLookup(hostRecord, NS_OK, ai, mPB, mOriginSuffix,
757 TRRSkippedReason::TRR_OK, this);
758}
759
760nsresult TRR::ReturnData(nsIChannel* aChannel) {
761 if (mType != TRRTYPE_TXT && mType != TRRTYPE_HTTPSSVC) {
762 // create and populate an AddrInfo instance to pass on
763 RefPtr<AddrInfo> ai(new AddrInfo(mHost, ResolverType(), mType,
764 nsTArray<NetAddr>(), mDNS.mTtl));
765 auto builder = ai->Build();
766 builder.SetAddresses(std::move(mDNS.mAddresses));
767 builder.SetCanonicalHostname(mCname);
768
769 // Set timings.
770 nsCOMPtr<nsITimedChannel> timedChan = do_QueryInterface(aChannel);
771 if (timedChan) {
772 TimeStamp asyncOpen, start, end;
773 if (NS_SUCCEEDED(timedChan->GetAsyncOpen(&asyncOpen))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChan->GetAsyncOpen
(&asyncOpen))), 1)))
&&
774 !asyncOpen.IsNull()) {
775 builder.SetTrrFetchDuration(
776 (TimeStamp::Now() - asyncOpen).ToMilliseconds());
777 }
778 if (NS_SUCCEEDED(timedChan->GetRequestStart(&start))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChan->GetRequestStart
(&start))), 1)))
&&
779 NS_SUCCEEDED(timedChan->GetResponseEnd(&end))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChan->GetResponseEnd
(&end))), 1)))
&& !start.IsNull() &&
780 !end.IsNull()) {
781 builder.SetTrrFetchDurationNetworkOnly((end - start).ToMilliseconds());
782 }
783 }
784 ai = builder.Finish();
785
786 if (!mHostResolver) {
787 return NS_ERROR_FAILURE;
788 }
789 RecordReason(TRRSkippedReason::TRR_OK);
790 (void)mHostResolver->CompleteLookup(mRec, NS_OK, ai, mPB, mOriginSuffix,
791 mTRRSkippedReason, this);
792 mHostResolver = nullptr;
793 mRec = nullptr;
794 } else {
795 RecordReason(TRRSkippedReason::TRR_OK);
796 (void)mHostResolver->CompleteLookupByType(mRec, NS_OK, mResult,
797 mTRRSkippedReason, mTTL, mPB);
798 }
799 return NS_OK;
800}
801
802nsresult TRR::FailData(nsresult error) {
803 if (!mHostResolver) {
804 return NS_ERROR_FAILURE;
805 }
806
807 // If we didn't record a reason until now, record a default one.
808 RecordReason(TRRSkippedReason::TRR_FAILED);
809
810 if (mType == TRRTYPE_TXT || mType == TRRTYPE_HTTPSSVC) {
811 TypeRecordResultType empty(Nothing{});
812 (void)mHostResolver->CompleteLookupByType(mRec, error, empty,
813 mTRRSkippedReason, 0, mPB);
814 } else {
815 // create and populate an TRR AddrInfo instance to pass on to signal that
816 // this comes from TRR
817 nsTArray<NetAddr> noAddresses;
818 RefPtr<AddrInfo> ai =
819 new AddrInfo(mHost, ResolverType(), mType, std::move(noAddresses));
820
821 (void)mHostResolver->CompleteLookup(mRec, error, ai, mPB, mOriginSuffix,
822 mTRRSkippedReason, this);
823 }
824
825 mHostResolver = nullptr;
826 mRec = nullptr;
827 return NS_OK;
828}
829
830void TRR::HandleDecodeError(nsresult aStatusCode) {
831 auto rcode = mPacket->GetRCode();
832 if (rcode.isOk() && rcode.unwrap() != 0) {
833 if (rcode.unwrap() == 0x03) {
834 RecordReason(TRRSkippedReason::TRR_NXDOMAIN);
835 } else {
836 RecordReason(TRRSkippedReason::TRR_RCODE_FAIL);
837 }
838 } else if (aStatusCode == NS_ERROR_UNKNOWN_HOST ||
839 aStatusCode == NS_ERROR_DEFINITIVE_UNKNOWN_HOST) {
840 RecordReason(TRRSkippedReason::TRR_NO_ANSWERS);
841 } else {
842 RecordReason(TRRSkippedReason::TRR_DECODE_FAILED);
843 }
844}
845
846bool TRR::HasUsableResponse() {
847 if (mType == TRRTYPE_A || mType == TRRTYPE_AAAA) {
848 return !mDNS.mAddresses.IsEmpty();
849 }
850 if (mType == TRRTYPE_TXT) {
851 return mResult.is<TypeRecordTxt>();
852 }
853 if (mType == TRRTYPE_HTTPSSVC) {
854 return mResult.is<TypeRecordHTTPSSVC>();
855 }
856 return false;
857}
858
859nsresult TRR::FollowCname(nsIChannel* aChannel) {
860 nsresult rv = NS_OK;
861 nsAutoCString cname;
862 while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mDNS.mAddresses.IsEmpty() && !mCname.IsEmpty() &&
863 mCnameLoop > 0) {
864 mCnameLoop--;
865 LOG(("TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(), mCname.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
866 mCnameLoop))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
;
867 cname = mCname;
868 mCname.Truncate();
869
870 LOG(("TRR: check for CNAME record for %s within previous response\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: check for CNAME record for %s within previous response\n"
, cname.get()); } } while (0)
871 cname.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: check for CNAME record for %s within previous response\n"
, cname.get()); } } while (0)
;
872 nsClassHashtable<nsCStringHashKey, DOHresp> additionalRecords;
873 rv = GetOrCreateDNSPacket()->Decode(
874 cname, mType, mCname, StaticPrefs::network_trr_allow_rfc1918(), mDNS,
875 mResult, additionalRecords, mTTL);
876 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
877 LOG(("TRR::FollowCname DohDecode %x\n", (int)rv))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::FollowCname DohDecode %x\n", (int)rv); } } while (0)
;
878 HandleDecodeError(rv);
879 }
880 }
881
882 // restore mCname as DohDecode() change it
883 mCname = cname;
884 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && HasUsableResponse()) {
885 ReturnData(aChannel);
886 return NS_OK;
887 }
888
889 bool ra = mPacket && mPacket->RecursionAvailable().unwrapOr(false);
890 LOG(("ra = %d", ra))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "ra = %d", ra); } } while (0)
;
891 if (rv == NS_ERROR_UNKNOWN_HOST && ra) {
892 // If recursion is available, but no addresses have been returned,
893 // we can just return a failure here.
894 LOG(("TRR::FollowCname not sending another request as RA flag is set."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::FollowCname not sending another request as RA flag is set."
); } } while (0)
;
895 FailData(NS_ERROR_UNKNOWN_HOST);
896 return NS_OK;
897 }
898
899 if (!mCnameLoop) {
900 LOG(("TRR::On200Response CNAME loop, eject!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME loop, eject!\n"); } } while (0)
;
901 return NS_ERROR_REDIRECT_LOOP;
902 }
903
904 LOG(("TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(), mCname.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
905 mCnameLoop))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
;
906 RefPtr<TRR> trr =
907 new TRR(mHostResolver, mRec, mCname, mType, mCnameLoop, mPB);
908 trr->SetPurpose(mPurpose);
909 if (!TRRService::Get()) {
910 return NS_ERROR_FAILURE;
911 }
912 return TRRService::Get()->DispatchTRRRequest(trr);
913}
914
915nsresult TRR::On200Response(nsIChannel* aChannel) {
916 // decode body and create an AddrInfo struct for the response
917 nsClassHashtable<nsCStringHashKey, DOHresp> additionalRecords;
918 RefPtr<TypeHostRecord> typeRec = do_QueryObject(mRec);
919 if (typeRec && typeRec->mOriginHost) {
920 GetOrCreateDNSPacket()->SetOriginHost(typeRec->mOriginHost);
921 }
922 nsresult rv = GetOrCreateDNSPacket()->Decode(
923 mHost, mType, mCname, StaticPrefs::network_trr_allow_rfc1918(), mDNS,
924 mResult, additionalRecords, mTTL);
925 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
926 LOG(("TRR::On200Response DohDecode %x\n", (int)rv))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response DohDecode %x\n", (int)rv); } } while (0
)
;
927 HandleDecodeError(rv);
928 return rv;
929 }
930 if (StaticPrefs::network_trr_add_additional_records()) {
931 SaveAdditionalRecords(additionalRecords);
932 }
933
934 if (mResult.is<TypeRecordHTTPSSVC>()) {
935 auto& results = mResult.as<TypeRecordHTTPSSVC>();
936 for (const auto& rec : results) {
937 StoreIPHintAsDNSRecord(rec);
938 }
939 }
940
941 if (!mDNS.mAddresses.IsEmpty() || mType == TRRTYPE_TXT || mCname.IsEmpty()) {
942 // pass back the response data
943 ReturnData(aChannel);
944 return NS_OK;
945 }
946
947 LOG(("TRR::On200Response trying CNAME %s", mCname.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response trying CNAME %s", mCname.get()); } } while
(0)
;
948 return FollowCname(aChannel);
949}
950
951void TRR::RecordProcessingTime(nsIChannel* aChannel) {
952 // This method records the time it took from the last received byte of the
953 // DoH response until we've notified the consumer with a host record.
954 nsCOMPtr<nsITimedChannel> timedChan = do_QueryInterface(aChannel);
955 if (!timedChan) {
956 return;
957 }
958 TimeStamp end;
959 if (NS_FAILED(timedChan->GetResponseEnd(&end))((bool)(__builtin_expect(!!(NS_FAILED_impl(timedChan->GetResponseEnd
(&end))), 0)))
) {
960 return;
961 }
962
963 if (end.IsNull()) {
964 return;
965 }
966
967 Telemetry::AccumulateTimeDelta(Telemetry::DNS_TRR_PROCESSING_TIME, end);
968
969 LOG(("Processing DoH response took %f ms",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Processing DoH response took %f ms", (TimeStamp::Now() - end
).ToMilliseconds()); } } while (0)
970 (TimeStamp::Now() - end).ToMilliseconds()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Processing DoH response took %f ms", (TimeStamp::Now() - end
).ToMilliseconds()); } } while (0)
;
971}
972
973void TRR::ReportStatus(nsresult aStatusCode) {
974 // If the TRR was cancelled by nsHostResolver, then we don't need to report
975 // it as failed; otherwise it can cause the confirmation to fail.
976 if (UseDefaultServer() && aStatusCode != NS_ERROR_ABORT) {
977 // Bad content is still considered "okay" if the HTTP response is okay
978 TRRService::Get()->RecordTRRStatus(this);
979 }
980}
981
982static void RecordHttpVersion(nsIHttpChannel* aHttpChannel) {
983 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
984 do_QueryInterface(aHttpChannel);
985 if (!internalChannel) {
986 LOG(("RecordHttpVersion: Failed to QI nsIHttpChannelInternal"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "RecordHttpVersion: Failed to QI nsIHttpChannelInternal"); }
} while (0)
;
987 return;
988 }
989
990 uint32_t major, minor;
991 if (NS_FAILED(internalChannel->GetResponseVersion(&major, &minor))((bool)(__builtin_expect(!!(NS_FAILED_impl(internalChannel->
GetResponseVersion(&major, &minor))), 0)))
) {
992 LOG(("RecordHttpVersion: Failed to get protocol version"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "RecordHttpVersion: Failed to get protocol version"); } } while
(0)
;
993 return;
994 }
995
996 auto label = Telemetry::LABELS_DNS_TRR_HTTP_VERSION2::h_1;
997 if (major == 2) {
998 label = Telemetry::LABELS_DNS_TRR_HTTP_VERSION2::h_2;
999 } else if (major == 3) {
1000 label = Telemetry::LABELS_DNS_TRR_HTTP_VERSION2::h_3;
1001 }
1002
1003 Telemetry::AccumulateCategoricalKeyed(TRRService::ProviderKey(), label);
1004
1005 LOG(("RecordHttpVersion: Provider responded using HTTP version: %d", major))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "RecordHttpVersion: Provider responded using HTTP version: %d"
, major); } } while (0)
;
1006}
1007
1008NS_IMETHODIMPnsresult
1009TRR::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
1010 // The dtor will be run after the function returns
1011 LOG(("TRR:OnStopRequest %p %s %d failed=%d code=%X\n", this, mHost.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d failed=%d code=%X\n", this, mHost
.get(), mType, mFailed, (unsigned int)aStatusCode); } } while
(0)
1012 mType, mFailed, (unsigned int)aStatusCode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d failed=%d code=%X\n", this, mHost
.get(), mType, mFailed, (unsigned int)aStatusCode); } } while
(0)
;
1013 nsCOMPtr<nsIChannel> channel;
1014 channel.swap(mChannel);
1015
1016 mChannelStatus = aStatusCode;
1017 if (NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1)
))
) {
1018 nsCString label = "regular"_ns;
1019 if (mPB) {
1020 label = "private"_ns;
1021 }
1022 mozilla::glean::networking::trr_request_count.Get(label).Add(1);
1023 }
1024
1025 {
1026 // Cancel the timer since we don't need it anymore.
1027 nsCOMPtr<nsITimer> timer;
1028 mTimeout.swap(timer);
1029 if (timer) {
1030 timer->Cancel();
1031 }
1032 }
1033
1034 auto scopeExit = MakeScopeExit([&] { ReportStatus(aStatusCode); });
1035
1036 nsresult rv = NS_OK;
1037 // if status was "fine", parse the response and pass on the answer
1038 if (!mFailed && NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1)
))
) {
1039 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
1040 if (!httpChannel) {
1041 return NS_ERROR_UNEXPECTED;
1042 }
1043 nsAutoCString contentType;
1044 httpChannel->GetContentType(contentType);
1045 if (contentType.Length() &&
1046 !contentType.LowerCaseEqualsASCII(ContentType())) {
1047 LOG(("TRR:OnStopRequest %p %s %d wrong content type %s\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d wrong content type %s\n", this,
mHost.get(), mType, contentType.get()); } } while (0)
1048 mHost.get(), mType, contentType.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d wrong content type %s\n", this,
mHost.get(), mType, contentType.get()); } } while (0)
;
1049 FailData(NS_ERROR_UNEXPECTED);
1050 return NS_OK;
1051 }
1052
1053 uint32_t httpStatus;
1054 rv = httpChannel->GetResponseStatus(&httpStatus);
1055 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && httpStatus == 200) {
1056 rv = On200Response(channel);
1057 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && UseDefaultServer()) {
1058 RecordReason(TRRSkippedReason::TRR_OK);
1059 RecordProcessingTime(channel);
1060 RecordHttpVersion(httpChannel);
1061 return rv;
1062 }
1063 } else {
1064 RecordReason(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR);
1065 LOG(("TRR:OnStopRequest:%d %p rv %x httpStatus %d\n", __LINE__, this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest:%d %p rv %x httpStatus %d\n", 1065, this
, (int)rv, httpStatus); } } while (0)
1066 (int)rv, httpStatus))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest:%d %p rv %x httpStatus %d\n", 1065, this
, (int)rv, httpStatus); } } while (0)
;
1067 }
1068 }
1069
1070 LOG(("TRR:OnStopRequest %p status %x mFailed %d\n", this, (int)aStatusCode,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p status %x mFailed %d\n", this, (int)aStatusCode
, mFailed); } } while (0)
1071 mFailed))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p status %x mFailed %d\n", this, (int)aStatusCode
, mFailed); } } while (0)
;
1072 FailData(NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? NS_ERROR_UNKNOWN_HOST : rv);
1073 return NS_OK;
1074}
1075
1076NS_IMETHODIMPnsresult
1077TRR::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream,
1078 uint64_t aOffset, const uint32_t aCount) {
1079 LOG(("TRR:OnDataAvailable %p %s %d failed=%d aCount=%u\n", this, mHost.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnDataAvailable %p %s %d failed=%d aCount=%u\n", this,
mHost.get(), mType, mFailed, (unsigned int)aCount); } } while
(0)
1080 mType, mFailed, (unsigned int)aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnDataAvailable %p %s %d failed=%d aCount=%u\n", this,
mHost.get(), mType, mFailed, (unsigned int)aCount); } } while
(0)
;
1081 // receive DNS response into the local buffer
1082 if (mFailed) {
1083 return NS_ERROR_FAILURE;
1084 }
1085
1086 nsresult rv = GetOrCreateDNSPacket()->OnDataAvailable(aRequest, aInputStream,
1087 aOffset, aCount);
1088 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1089 LOG(("TRR::OnDataAvailable:%d fail\n", __LINE__))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::OnDataAvailable:%d fail\n", 1089); } } while (0)
;
1090 mFailed = true;
1091 return rv;
1092 }
1093 return NS_OK;
1094}
1095
1096void TRR::Cancel(nsresult aStatus) {
1097 bool isTRRServiceChannel = false;
1098 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
1099 do_QueryInterface(mChannel));
1100 if (httpChannelInternal) {
1101 nsresult rv =
1102 httpChannelInternal->GetIsTRRServiceChannel(&isTRRServiceChannel);
1103 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1104 isTRRServiceChannel = false;
1105 }
1106 }
1107 // nsHttpChannel can be only canceled on the main thread.
1108 RefPtr<nsHttpChannel> httpChannel = do_QueryObject(mChannel);
1109 if (isTRRServiceChannel && !XRE_IsSocketProcess() && !httpChannel) {
1110 if (TRRService::Get()) {
1111 nsCOMPtr<nsIThread> thread = TRRService::Get()->TRRThread();
1112 if (thread && !thread->IsOnCurrentThread()) {
1113 thread->Dispatch(NS_NewRunnableFunction(
1114 "TRR::Cancel",
1115 [self = RefPtr(this), aStatus]() { self->Cancel(aStatus); }));
1116 return;
1117 }
1118 }
1119 } else {
1120 if (!NS_IsMainThread()) {
1121 NS_DispatchToMainThread(NS_NewRunnableFunction(
1122 "TRR::Cancel",
1123 [self = RefPtr(this), aStatus]() { self->Cancel(aStatus); }));
1124 return;
1125 }
1126 }
1127
1128 if (mCancelled) {
1129 return;
1130 }
1131 mCancelled = true;
1132
1133 if (mChannel) {
1134 RecordReason(TRRSkippedReason::TRR_REQ_CANCELLED);
1135 LOG(("TRR: %p canceling Channel %p %s %d status=%" PRIx32 "\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: %p canceling Channel %p %s %d status=%" "x" "\n", this
, mChannel.get(), mHost.get(), mType, static_cast<uint32_t
>(aStatus)); } } while (0)
1136 mChannel.get(), mHost.get(), mType, static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: %p canceling Channel %p %s %d status=%" "x" "\n", this
, mChannel.get(), mHost.get(), mType, static_cast<uint32_t
>(aStatus)); } } while (0)
;
1137 mChannel->Cancel(aStatus);
1138 }
1139}
1140
1141bool TRR::UseDefaultServer() { return !mRec || mRec->mTrrServer.IsEmpty(); }
1142
1143} // namespace net
1144} // namespace mozilla