Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp
Warning:line 2676, column 3
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_protocol_websocket0.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/protocol/websocket -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/websocket -resource-dir /usr/lib/llvm-20/lib/clang/20 -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 _GLIBCXX_ASSERTIONS -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/protocol/websocket -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/websocket -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/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -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-20/lib/clang/20/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-2025-01-20-090804-167946-1 -x c++ Unified_cpp_protocol_websocket0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set sw=2 ts=8 et tw=80 : */
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 <algorithm>
8
9#include "WebSocketChannel.h"
10
11#include "WebSocketConnectionBase.h"
12#include "WebSocketFrame.h"
13#include "WebSocketLog.h"
14#include "mozilla/Atomics.h"
15#include "mozilla/Attributes.h"
16#include "mozilla/Base64.h"
17#include "mozilla/Components.h"
18#include "mozilla/EndianUtils.h"
19#include "mozilla/MathAlgorithms.h"
20#include "mozilla/ScopeExit.h"
21#include "mozilla/StaticMutex.h"
22#include "mozilla/StaticPrefs_privacy.h"
23#include "mozilla/Telemetry.h"
24#include "mozilla/TimeStamp.h"
25#include "mozilla/Utf8.h"
26#include "mozilla/net/WebSocketEventService.h"
27#include "nsCRT.h"
28#include "nsCharSeparatedTokenizer.h"
29#include "nsComponentManagerUtils.h"
30#include "nsError.h"
31#include "nsIAsyncVerifyRedirectCallback.h"
32#include "nsICancelable.h"
33#include "nsIChannel.h"
34#include "nsIClassOfService.h"
35#include "nsICryptoHash.h"
36#include "nsIDNSRecord.h"
37#include "nsIDNSService.h"
38#include "nsIDashboardEventNotifier.h"
39#include "nsIEventTarget.h"
40#include "nsIHttpChannel.h"
41#include "nsIIOService.h"
42#include "nsINSSErrorsService.h"
43#include "nsINetworkLinkService.h"
44#include "nsINode.h"
45#include "nsIObserverService.h"
46#include "nsIPrefBranch.h"
47#include "nsIProtocolHandler.h"
48#include "nsIProtocolProxyService.h"
49#include "nsIProxiedChannel.h"
50#include "nsIProxyInfo.h"
51#include "nsIRandomGenerator.h"
52#include "nsIRunnable.h"
53#include "nsISocketTransport.h"
54#include "nsITLSSocketControl.h"
55#include "nsITransportProvider.h"
56#include "nsITransportSecurityInfo.h"
57#include "nsIURI.h"
58#include "nsIURIMutator.h"
59#include "nsNetCID.h"
60#include "nsNetUtil.h"
61#include "nsProxyRelease.h"
62#include "nsServiceManagerUtils.h"
63#include "nsSocketTransportService2.h"
64#include "nsStringStream.h"
65#include "nsThreadUtils.h"
66#include "plbase64.h"
67#include "prmem.h"
68#include "prnetdb.h"
69#include "zlib.h"
70
71// rather than slurp up all of nsIWebSocket.idl, which lives outside necko, just
72// dupe one constant we need from it
73#define CLOSE_GOING_AWAY 1001
74
75using namespace mozilla;
76using namespace mozilla::net;
77
78namespace mozilla::net {
79
80NS_IMPL_ISUPPORTS(WebSocketChannel, nsIWebSocketChannel, nsIHttpUpgradeListener,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert
(!std::is_destructible_v<WebSocketChannel>, "Reference-counted class "
"WebSocketChannel" " 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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
85; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 85
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); const char* const nametmp
= "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsIWebSocketChannel>
, int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel
*>((WebSocketChannel*)0x1000)) - reinterpret_cast<char*
>((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIStreamListener>, int32_t( reinterpret_cast<char*>
(static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolHandler>, int32_t( reinterpret_cast<char*>
(static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIOutputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsITimerCallback>, int32_t( reinterpret_cast<char*>
(static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIDNSListener>, int32_t( reinterpret_cast<char*>(
static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000)
) - reinterpret_cast<char*>((WebSocketChannel*)0x1000))
}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolProxyCallback>, int32_t( reinterpret_cast<
char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIThreadRetargetableRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIThreadRetargetableRequest*>
((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>(
(WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast
<char*>(static_cast<nsIObserver*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsINamed>, int32_t( reinterpret_cast<char*>(static_cast
<nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast
<char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIWebSocketChannel*>((WebSocketChannel*)
0x1000))) - reinterpret_cast<char*>((WebSocketChannel*)
0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
81 nsIRequestObserver, nsIStreamListener, nsIProtocolHandler,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert
(!std::is_destructible_v<WebSocketChannel>, "Reference-counted class "
"WebSocketChannel" " 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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
85; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 85
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); const char* const nametmp
= "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsIWebSocketChannel>
, int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel
*>((WebSocketChannel*)0x1000)) - reinterpret_cast<char*
>((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIStreamListener>, int32_t( reinterpret_cast<char*>
(static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolHandler>, int32_t( reinterpret_cast<char*>
(static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIOutputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsITimerCallback>, int32_t( reinterpret_cast<char*>
(static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIDNSListener>, int32_t( reinterpret_cast<char*>(
static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000)
) - reinterpret_cast<char*>((WebSocketChannel*)0x1000))
}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolProxyCallback>, int32_t( reinterpret_cast<
char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIThreadRetargetableRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIThreadRetargetableRequest*>
((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>(
(WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast
<char*>(static_cast<nsIObserver*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsINamed>, int32_t( reinterpret_cast<char*>(static_cast
<nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast
<char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIWebSocketChannel*>((WebSocketChannel*)
0x1000))) - reinterpret_cast<char*>((WebSocketChannel*)
0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
82 nsIInputStreamCallback, nsIOutputStreamCallback,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert
(!std::is_destructible_v<WebSocketChannel>, "Reference-counted class "
"WebSocketChannel" " 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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
85; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 85
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); const char* const nametmp
= "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsIWebSocketChannel>
, int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel
*>((WebSocketChannel*)0x1000)) - reinterpret_cast<char*
>((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIStreamListener>, int32_t( reinterpret_cast<char*>
(static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolHandler>, int32_t( reinterpret_cast<char*>
(static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIOutputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsITimerCallback>, int32_t( reinterpret_cast<char*>
(static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIDNSListener>, int32_t( reinterpret_cast<char*>(
static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000)
) - reinterpret_cast<char*>((WebSocketChannel*)0x1000))
}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolProxyCallback>, int32_t( reinterpret_cast<
char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIThreadRetargetableRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIThreadRetargetableRequest*>
((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>(
(WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast
<char*>(static_cast<nsIObserver*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsINamed>, int32_t( reinterpret_cast<char*>(static_cast
<nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast
<char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIWebSocketChannel*>((WebSocketChannel*)
0x1000))) - reinterpret_cast<char*>((WebSocketChannel*)
0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
83 nsITimerCallback, nsIDNSListener, nsIProtocolProxyCallback,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert
(!std::is_destructible_v<WebSocketChannel>, "Reference-counted class "
"WebSocketChannel" " 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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
85; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 85
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); const char* const nametmp
= "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsIWebSocketChannel>
, int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel
*>((WebSocketChannel*)0x1000)) - reinterpret_cast<char*
>((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIStreamListener>, int32_t( reinterpret_cast<char*>
(static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolHandler>, int32_t( reinterpret_cast<char*>
(static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIOutputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsITimerCallback>, int32_t( reinterpret_cast<char*>
(static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIDNSListener>, int32_t( reinterpret_cast<char*>(
static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000)
) - reinterpret_cast<char*>((WebSocketChannel*)0x1000))
}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolProxyCallback>, int32_t( reinterpret_cast<
char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIThreadRetargetableRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIThreadRetargetableRequest*>
((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>(
(WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast
<char*>(static_cast<nsIObserver*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsINamed>, int32_t( reinterpret_cast<char*>(static_cast
<nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast
<char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIWebSocketChannel*>((WebSocketChannel*)
0x1000))) - reinterpret_cast<char*>((WebSocketChannel*)
0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
84 nsIInterfaceRequestor, nsIChannelEventSink,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert
(!std::is_destructible_v<WebSocketChannel>, "Reference-counted class "
"WebSocketChannel" " 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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
85; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 85
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); const char* const nametmp
= "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsIWebSocketChannel>
, int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel
*>((WebSocketChannel*)0x1000)) - reinterpret_cast<char*
>((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIStreamListener>, int32_t( reinterpret_cast<char*>
(static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolHandler>, int32_t( reinterpret_cast<char*>
(static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIOutputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsITimerCallback>, int32_t( reinterpret_cast<char*>
(static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIDNSListener>, int32_t( reinterpret_cast<char*>(
static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000)
) - reinterpret_cast<char*>((WebSocketChannel*)0x1000))
}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolProxyCallback>, int32_t( reinterpret_cast<
char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIThreadRetargetableRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIThreadRetargetableRequest*>
((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>(
(WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast
<char*>(static_cast<nsIObserver*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsINamed>, int32_t( reinterpret_cast<char*>(static_cast
<nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast
<char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIWebSocketChannel*>((WebSocketChannel*)
0x1000))) - reinterpret_cast<char*>((WebSocketChannel*)
0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
85 nsIThreadRetargetableRequest, nsIObserver, nsINamed)MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert
(!std::is_destructible_v<WebSocketChannel>, "Reference-counted class "
"WebSocketChannel" " 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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
85; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 85
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 85; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("WebSocketChannel" " not thread-safe"); const char* const nametmp
= "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult WebSocketChannel
::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/protocol/websocket/WebSocketChannel.cpp"
, 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsIWebSocketChannel>
, int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel
*>((WebSocketChannel*)0x1000)) - reinterpret_cast<char*
>((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIStreamListener>, int32_t( reinterpret_cast<char*>
(static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolHandler>, int32_t( reinterpret_cast<char*>
(static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIOutputStreamCallback>, int32_t( reinterpret_cast<char
*>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsITimerCallback>, int32_t( reinterpret_cast<char*>
(static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000
)) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)
)}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIDNSListener>, int32_t( reinterpret_cast<char*>(
static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000)
) - reinterpret_cast<char*>((WebSocketChannel*)0x1000))
}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIProtocolProxyCallback>, int32_t( reinterpret_cast<
char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsIThreadRetargetableRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIThreadRetargetableRequest*>
((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>(
(WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID
<WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast
<char*>(static_cast<nsIObserver*>((WebSocketChannel
*)0x1000)) - reinterpret_cast<char*>((WebSocketChannel*
)0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel
, nsINamed>, int32_t( reinterpret_cast<char*>(static_cast
<nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast
<char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail
::kImplementedIID<WebSocketChannel, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIWebSocketChannel*>((WebSocketChannel*)
0x1000))) - reinterpret_cast<char*>((WebSocketChannel*)
0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
86
87// We implement RFC 6455, which uses Sec-WebSocket-Version: 13 on the wire.
88#define SEC_WEBSOCKET_VERSION"13" "13"
89
90/*
91 * About SSL unsigned certificates
92 *
93 * wss will not work to a host using an unsigned certificate unless there
94 * is already an exception (i.e. it cannot popup a dialog asking for
95 * a security exception). This is similar to how an inlined img will
96 * fail without a dialog if fails for the same reason. This should not
97 * be a problem in practice as it is expected the websocket javascript
98 * is served from the same host as the websocket server (or of course,
99 * a valid cert could just be provided).
100 *
101 */
102
103// some helper classes
104
105//-----------------------------------------------------------------------------
106// FailDelayManager
107//
108// Stores entries (searchable by {host, port}) of connections that have recently
109// failed, so we can do delay of reconnects per RFC 6455 Section 7.2.3
110//-----------------------------------------------------------------------------
111
112// Initial reconnect delay is randomly chosen between 200-400 ms.
113// This is a gentler backoff than the 0-5 seconds the spec offhandedly suggests.
114const uint32_t kWSReconnectInitialBaseDelay = 200;
115const uint32_t kWSReconnectInitialRandomDelay = 200;
116
117// Base lifetime (in ms) of a FailDelay: kept longer if more failures occur
118const uint32_t kWSReconnectBaseLifeTime = 60 * 1000;
119// Maximum reconnect delay (in ms)
120const uint32_t kWSReconnectMaxDelay = 60 * 1000;
121
122// hold record of failed connections, and calculates needed delay for reconnects
123// to same host/path/port.
124class FailDelay {
125 public:
126 FailDelay(nsCString address, nsCString path, int32_t port)
127 : mAddress(std::move(address)), mPath(std::move(path)), mPort(port) {
128 mLastFailure = TimeStamp::Now();
129 mNextDelay = kWSReconnectInitialBaseDelay +
130 (rand() % kWSReconnectInitialRandomDelay);
131 }
132
133 // Called to update settings when connection fails again.
134 void FailedAgain() {
135 mLastFailure = TimeStamp::Now();
136 // We use a truncated exponential backoff as suggested by RFC 6455,
137 // but multiply by 1.5 instead of 2 to be more gradual.
138 mNextDelay = static_cast<uint32_t>(
139 std::min<double>(kWSReconnectMaxDelay, mNextDelay * 1.5));
140 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "
"to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay
); } } while (0)
141 ("WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "
"to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay
); } } while (0)
142 "to "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "
"to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay
); } } while (0)
143 "%" PRIu32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "
"to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay
); } } while (0)
144 mAddress.get(), mPath.get(), mPort, mNextDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "
"to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay
); } } while (0)
;
145 }
146
147 // returns 0 if there is no need to delay (i.e. delay interval is over)
148 uint32_t RemainingDelay(TimeStamp rightNow) {
149 TimeDuration dur = rightNow - mLastFailure;
150 uint32_t sinceFail = (uint32_t)dur.ToMilliseconds();
151 if (sinceFail > mNextDelay) return 0;
152
153 return mNextDelay - sinceFail;
154 }
155
156 bool IsExpired(TimeStamp rightNow) {
157 return (mLastFailure + TimeDuration::FromMilliseconds(
158 kWSReconnectBaseLifeTime + mNextDelay)) <=
159 rightNow;
160 }
161
162 nsCString mAddress; // IP address (or hostname if using proxy)
163 nsCString mPath;
164 int32_t mPort;
165
166 private:
167 TimeStamp mLastFailure; // Time of last failed attempt
168 // mLastFailure + mNextDelay is the soonest we'll allow a reconnect
169 uint32_t mNextDelay; // milliseconds
170};
171
172class FailDelayManager {
173 public:
174 FailDelayManager() {
175 MOZ_COUNT_CTOR(FailDelayManager)do { static_assert(std::is_class_v<FailDelayManager>, "Token '"
"FailDelayManager" "' is not a class type."); static_assert(
!std::is_base_of<nsISupports, FailDelayManager>::value,
"nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR"
);; NS_LogCtor((void*)this, "FailDelayManager", sizeof(*this)
); } while (0)
;
176
177 mDelaysDisabled = false;
178
179 nsCOMPtr<nsIPrefBranch> prefService;
180 prefService = mozilla::components::Preferences::Service();
181 if (!prefService) {
182 return;
183 }
184 bool boolpref = true;
185 nsresult rv;
186 rv = prefService->GetBoolPref("network.websocket.delay-failed-reconnects",
187 &boolpref);
188 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !boolpref) {
189 mDelaysDisabled = true;
190 }
191 }
192
193 ~FailDelayManager() { MOZ_COUNT_DTOR(FailDelayManager)do { static_assert(std::is_class_v<FailDelayManager>, "Token '"
"FailDelayManager" "' is not a class type."); static_assert(
!std::is_base_of<nsISupports, FailDelayManager>::value,
"nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR"
);; NS_LogDtor((void*)this, "FailDelayManager", sizeof(*this)
); } while (0)
; }
194
195 void Add(nsCString& address, nsCString& path, int32_t port) {
196 if (mDelaysDisabled) return;
197
198 UniquePtr<FailDelay> record(new FailDelay(address, path, port));
199 mEntries.AppendElement(std::move(record));
200 }
201
202 // Element returned may not be valid after next main thread event: don't keep
203 // pointer to it around
204 FailDelay* Lookup(nsCString& address, nsCString& path, int32_t port,
205 uint32_t* outIndex = nullptr) {
206 if (mDelaysDisabled) return nullptr;
207
208 FailDelay* result = nullptr;
209 TimeStamp rightNow = TimeStamp::Now();
210
211 // We also remove expired entries during search: iterate from end to make
212 // indexing simpler
213 for (int32_t i = mEntries.Length() - 1; i >= 0; --i) {
214 FailDelay* fail = mEntries[i].get();
215 if (fail->mAddress.Equals(address) && fail->mPath.Equals(path) &&
216 fail->mPort == port) {
217 if (outIndex) *outIndex = i;
218 result = fail;
219 // break here: removing more entries would mess up *outIndex.
220 // Any remaining expired entries will be deleted next time Lookup
221 // finds nothing, which is the most common case anyway.
222 break;
223 }
224 if (fail->IsExpired(rightNow)) {
225 mEntries.RemoveElementAt(i);
226 }
227 }
228 return result;
229 }
230
231 // returns true if channel connects immediately, or false if it's delayed
232 void DelayOrBegin(WebSocketChannel* ws) {
233 if (!mDelaysDisabled) {
234 uint32_t failIndex = 0;
235 FailDelay* fail = Lookup(ws->mAddress, ws->mPath, ws->mPort, &failIndex);
236
237 if (fail) {
238 TimeStamp rightNow = TimeStamp::Now();
239
240 uint32_t remainingDelay = fail->RemainingDelay(rightNow);
241 if (remainingDelay) {
242 // reconnecting within delay interval: delay by remaining time
243 nsresult rv;
244 MutexAutoLock lock(ws->mMutex);
245 rv = NS_NewTimerWithCallback(getter_AddRefs(ws->mReconnectDelayTimer),
246 ws, remainingDelay,
247 nsITimer::TYPE_ONE_SHOT);
248 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
249 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing"
" state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay
); } } while (0)
250 ("WebSocket: delaying websocket [this=%p] by %lu ms, changing"do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing"
" state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay
); } } while (0)
251 " state to CONNECTING_DELAYED",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing"
" state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay
); } } while (0)
252 ws, (unsigned long)remainingDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing"
" state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay
); } } while (0)
;
253 ws->mConnecting = CONNECTING_DELAYED;
254 return;
255 }
256 // if timer fails (which is very unlikely), drop down to BeginOpen
257 // call
258 } else if (fail->IsExpired(rightNow)) {
259 mEntries.RemoveElementAt(failIndex);
260 }
261 }
262 }
263
264 // Delays disabled, or no previous failure, or we're reconnecting after
265 // scheduled delay interval has passed: connect.
266 ws->BeginOpen(true);
267 }
268
269 // Remove() also deletes all expired entries as it iterates: better for
270 // battery life than using a periodic timer.
271 void Remove(nsCString& address, nsCString& path, int32_t port) {
272 TimeStamp rightNow = TimeStamp::Now();
273
274 // iterate from end, to make deletion indexing easier
275 for (int32_t i = mEntries.Length() - 1; i >= 0; --i) {
276 FailDelay* entry = mEntries[i].get();
277 if ((entry->mAddress.Equals(address) && entry->mPath.Equals(path) &&
278 entry->mPort == port) ||
279 entry->IsExpired(rightNow)) {
280 mEntries.RemoveElementAt(i);
281 }
282 }
283 }
284
285 private:
286 nsTArray<UniquePtr<FailDelay>> mEntries;
287 bool mDelaysDisabled;
288};
289
290//-----------------------------------------------------------------------------
291// nsWSAdmissionManager
292//
293// 1) Ensures that only one websocket at a time is CONNECTING to a given IP
294// address (or hostname, if using proxy), per RFC 6455 Section 4.1.
295// 2) Delays reconnects to IP/host after connection failure, per Section 7.2.3
296//-----------------------------------------------------------------------------
297
298class nsWSAdmissionManager {
299 public:
300 static void Init() {
301 StaticMutexAutoLock lock(sLock);
302 if (!sManager) {
303 sManager = new nsWSAdmissionManager();
304 }
305 }
306
307 static void Shutdown() {
308 StaticMutexAutoLock lock(sLock);
309 delete sManager;
310 sManager = nullptr;
311 }
312
313 // Determine if we will open connection immediately (returns true), or
314 // delay/queue the connection (returns false)
315 static void ConditionallyConnect(WebSocketChannel* ws) {
316 LOG(("Websocket: ConditionallyConnect: [this=%p]", ws))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: ConditionallyConnect: [this=%p]"
, ws); } } while (0)
;
317 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
317; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
318 MOZ_ASSERT(ws->mConnecting == NOT_CONNECTING, "opening state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ws->mConnecting == NOT_CONNECTING)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ws->mConnecting == NOT_CONNECTING
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"ws->mConnecting == NOT_CONNECTING" " (" "opening state" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ws->mConnecting == NOT_CONNECTING"
") (" "opening state" ")"); do { *((volatile int*)__null) = 318
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
319
320 StaticMutexAutoLock lock(sLock);
321 if (!sManager) {
322 return;
323 }
324
325 // If there is already another WS channel connecting to this IP address,
326 // defer BeginOpen and mark as waiting in queue.
327 bool hostFound = (sManager->IndexOf(ws->mAddress, ws->mOriginSuffix) >= 0);
328
329 uint32_t failIndex = 0;
330 FailDelay* fail = sManager->mFailures.Lookup(ws->mAddress, ws->mPath,
331 ws->mPort, &failIndex);
332 bool existingFail = fail != nullptr;
333
334 // Always add ourselves to queue, even if we'll connect immediately
335 UniquePtr<nsOpenConn> newdata(
336 new nsOpenConn(ws->mAddress, ws->mOriginSuffix, existingFail, ws));
337
338 // If a connection has not previously failed then prioritize it over
339 // connections that have
340 if (existingFail) {
341 sManager->mQueue.AppendElement(std::move(newdata));
342 } else {
343 uint32_t insertionIndex = sManager->IndexOfFirstFailure();
344 MOZ_ASSERT(insertionIndex <= sManager->mQueue.Length(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(insertionIndex <= sManager->mQueue.Length())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(insertionIndex <= sManager->mQueue.Length())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("insertionIndex <= sManager->mQueue.Length()"
" (" "Insertion index outside bounds" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()"
") (" "Insertion index outside bounds" ")"); do { *((volatile
int*)__null) = 345; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
345 "Insertion index outside bounds")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(insertionIndex <= sManager->mQueue.Length())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(insertionIndex <= sManager->mQueue.Length())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("insertionIndex <= sManager->mQueue.Length()"
" (" "Insertion index outside bounds" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()"
") (" "Insertion index outside bounds" ")"); do { *((volatile
int*)__null) = 345; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
346 sManager->mQueue.InsertElementAt(insertionIndex, std::move(newdata));
347 }
348
349 if (hostFound) {
350 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to "
"CONNECTING_QUEUED"); } } while (0)
351 ("Websocket: some other channel is connecting, changing state to "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to "
"CONNECTING_QUEUED"); } } while (0)
352 "CONNECTING_QUEUED"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to "
"CONNECTING_QUEUED"); } } while (0)
;
353 ws->mConnecting = CONNECTING_QUEUED;
354 } else {
355 sManager->mFailures.DelayOrBegin(ws);
356 }
357 }
358
359 static void OnConnected(WebSocketChannel* aChannel) {
360 LOG(("Websocket: OnConnected: [this=%p]", aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnConnected: [this=%p]"
, aChannel); } } while (0)
;
361
362 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
362; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
363 MOZ_ASSERT(aChannel->mConnecting == CONNECTING_IN_PROGRESS,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChannel->mConnecting == CONNECTING_IN_PROGRESS)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChannel->mConnecting == CONNECTING_IN_PROGRESS))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChannel->mConnecting == CONNECTING_IN_PROGRESS"
" (" "Channel completed connect, but not connecting?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS"
") (" "Channel completed connect, but not connecting?" ")");
do { *((volatile int*)__null) = 364; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
364 "Channel completed connect, but not connecting?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChannel->mConnecting == CONNECTING_IN_PROGRESS)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChannel->mConnecting == CONNECTING_IN_PROGRESS))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChannel->mConnecting == CONNECTING_IN_PROGRESS"
" (" "Channel completed connect, but not connecting?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS"
") (" "Channel completed connect, but not connecting?" ")");
do { *((volatile int*)__null) = 364; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
365
366 StaticMutexAutoLock lock(sLock);
367 if (!sManager) {
368 return;
369 }
370
371 LOG(("Websocket: changing state to NOT_CONNECTING"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to NOT_CONNECTING"
); } } while (0)
;
372 aChannel->mConnecting = NOT_CONNECTING;
373
374 // Remove from queue
375 sManager->RemoveFromQueue(aChannel);
376
377 // Connection succeeded, so stop keeping track of any previous failures
378 sManager->mFailures.Remove(aChannel->mAddress, aChannel->mPath,
379 aChannel->mPort);
380
381 // Check for queued connections to same host.
382 // Note: still need to check for failures, since next websocket with same
383 // host may have different port
384 sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix);
385 }
386
387 // Called every time a websocket channel ends its session (including going
388 // away w/o ever successfully creating a connection)
389 static void OnStopSession(WebSocketChannel* aChannel, nsresult aReason) {
390 LOG(("Websocket: OnStopSession: [this=%p, reason=0x%08" PRIx32 "]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnStopSession: [this=%p, reason=0x%08"
"x" "]", aChannel, static_cast<uint32_t>(aReason)); } }
while (0)
391 aChannel, static_cast<uint32_t>(aReason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnStopSession: [this=%p, reason=0x%08"
"x" "]", aChannel, static_cast<uint32_t>(aReason)); } }
while (0)
;
392
393 StaticMutexAutoLock lock(sLock);
394 if (!sManager) {
395 return;
396 }
397
398 if (NS_FAILED(aReason)((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0)))) {
399 // Have we seen this failure before?
400 FailDelay* knownFailure = sManager->mFailures.Lookup(
401 aChannel->mAddress, aChannel->mPath, aChannel->mPort);
402 if (knownFailure) {
403 if (aReason == NS_ERROR_NOT_CONNECTED) {
404 // Don't count close() before connection as a network error
405 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed"
" [this=%p]", aChannel->mAddress.get(), aChannel->mPath
.get(), (int)aChannel->mPort, aChannel); } } while (0)
406 ("Websocket close() before connection to %s, %s, %d completed"do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed"
" [this=%p]", aChannel->mAddress.get(), aChannel->mPath
.get(), (int)aChannel->mPort, aChannel); } } while (0)
407 " [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed"
" [this=%p]", aChannel->mAddress.get(), aChannel->mPath
.get(), (int)aChannel->mPort, aChannel); } } while (0)
408 aChannel->mAddress.get(), aChannel->mPath.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed"
" [this=%p]", aChannel->mAddress.get(), aChannel->mPath
.get(), (int)aChannel->mPort, aChannel); } } while (0)
409 (int)aChannel->mPort, aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed"
" [this=%p]", aChannel->mAddress.get(), aChannel->mPath
.get(), (int)aChannel->mPort, aChannel); } } while (0)
;
410 } else {
411 // repeated failure to connect: increase delay for next connection
412 knownFailure->FailedAgain();
413 }
414 } else {
415 // new connection failure: record it.
416 LOG(("WebSocket: connection to %s, %s, %d failed: [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]"
, aChannel->mAddress.get(), aChannel->mPath.get(), (int
)aChannel->mPort, aChannel); } } while (0)
417 aChannel->mAddress.get(), aChannel->mPath.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]"
, aChannel->mAddress.get(), aChannel->mPath.get(), (int
)aChannel->mPort, aChannel); } } while (0)
418 (int)aChannel->mPort, aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]"
, aChannel->mAddress.get(), aChannel->mPath.get(), (int
)aChannel->mPort, aChannel); } } while (0)
;
419 sManager->mFailures.Add(aChannel->mAddress, aChannel->mPath,
420 aChannel->mPort);
421 }
422 }
423
424 if (NS_IsMainThread()) {
425 ContinueOnStopSession(aChannel, aReason);
426 } else {
427 NS_DispatchToMainThread(NS_NewRunnableFunction(
428 "nsWSAdmissionManager::ContinueOnStopSession",
429 [channel = RefPtr{aChannel}, reason = aReason]() {
430 StaticMutexAutoLock lock(sLock);
431 if (!sManager) {
432 return;
433 }
434
435 nsWSAdmissionManager::ContinueOnStopSession(channel, reason);
436 }));
437 }
438 }
439
440 static void ContinueOnStopSession(WebSocketChannel* aChannel,
441 nsresult aReason) {
442 sLock.AssertCurrentThreadOwns();
443 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
443; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
444
445 if (!aChannel->mConnecting) {
446 return;
447 }
448
449 // Only way a connecting channel may get here w/o failing is if it
450 // was closed with GOING_AWAY (1001) because of navigation, tab
451 // close, etc.
452#ifdef DEBUG1
453 {
454 MutexAutoLock lock(aChannel->mMutex);
455 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason))
, 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason))
, 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY"
" (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY"
") (" "websocket closed while connecting w/o failing?" ")");
do { *((volatile int*)__null) = 457; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
456 NS_FAILED(aReason) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason))
, 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason))
, 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY"
" (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY"
") (" "websocket closed while connecting w/o failing?" ")");
do { *((volatile int*)__null) = 457; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
457 "websocket closed while connecting w/o failing?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason))
, 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason))
, 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY"
" (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY"
") (" "websocket closed while connecting w/o failing?" ")");
do { *((volatile int*)__null) = 457; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
458 }
459#endif
460 Unused << aReason;
461
462 sManager->RemoveFromQueue(aChannel);
463
464 bool wasNotQueued = (aChannel->mConnecting != CONNECTING_QUEUED);
465 LOG(("Websocket: changing state to NOT_CONNECTING"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to NOT_CONNECTING"
); } } while (0)
;
466 aChannel->mConnecting = NOT_CONNECTING;
467 if (wasNotQueued) {
468 sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix);
469 }
470 }
471
472 static void IncrementSessionCount() {
473 StaticMutexAutoLock lock(sLock);
474 if (!sManager) {
475 return;
476 }
477 sManager->mSessionCount++;
478 }
479
480 static void DecrementSessionCount() {
481 StaticMutexAutoLock lock(sLock);
482 if (!sManager) {
483 return;
484 }
485 sManager->mSessionCount--;
486 }
487
488 static void GetSessionCount(int32_t& aSessionCount) {
489 StaticMutexAutoLock lock(sLock);
490 if (!sManager) {
491 return;
492 }
493 aSessionCount = sManager->mSessionCount;
494 }
495
496 private:
497 nsWSAdmissionManager() : mSessionCount(0) {
498 MOZ_COUNT_CTOR(nsWSAdmissionManager)do { static_assert(std::is_class_v<nsWSAdmissionManager>
, "Token '" "nsWSAdmissionManager" "' is not a class type.");
static_assert(!std::is_base_of<nsISupports, nsWSAdmissionManager
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsWSAdmissionManager"
, sizeof(*this)); } while (0)
;
499 }
500
501 ~nsWSAdmissionManager() { MOZ_COUNT_DTOR(nsWSAdmissionManager)do { static_assert(std::is_class_v<nsWSAdmissionManager>
, "Token '" "nsWSAdmissionManager" "' is not a class type.");
static_assert(!std::is_base_of<nsISupports, nsWSAdmissionManager
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsWSAdmissionManager"
, sizeof(*this)); } while (0)
; }
502
503 class nsOpenConn {
504 public:
505 nsOpenConn(nsCString& addr, nsCString& originSuffix, bool failed,
506 WebSocketChannel* channel)
507 : mAddress(addr),
508 mOriginSuffix(originSuffix),
509 mFailed(failed),
510 mChannel(channel) {
511 MOZ_COUNT_CTOR(nsOpenConn)do { static_assert(std::is_class_v<nsOpenConn>, "Token '"
"nsOpenConn" "' is not a class type."); static_assert(!std::
is_base_of<nsISupports, nsOpenConn>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsOpenConn", sizeof
(*this)); } while (0)
;
512 }
513 MOZ_COUNTED_DTOR(nsOpenConn)~nsOpenConn() { do { static_assert(std::is_class_v<nsOpenConn
>, "Token '" "nsOpenConn" "' is not a class type."); static_assert
(!std::is_base_of<nsISupports, nsOpenConn>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsOpenConn", sizeof
(*this)); } while (0); }
514
515 nsCString mAddress;
516 nsCString mOriginSuffix;
517 bool mFailed = false;
518 RefPtr<WebSocketChannel> mChannel;
519 };
520
521 void ConnectNext(nsCString& hostName, nsCString& originSuffix) {
522 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
522; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
523
524 int32_t index = IndexOf(hostName, originSuffix);
525 if (index >= 0) {
526 WebSocketChannel* chan = mQueue[index]->mChannel;
527
528 MOZ_ASSERT(chan->mConnecting == CONNECTING_QUEUED,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(chan->mConnecting == CONNECTING_QUEUED)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(chan->mConnecting == CONNECTING_QUEUED))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("chan->mConnecting == CONNECTING_QUEUED"
" (" "transaction not queued but in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED"
") (" "transaction not queued but in queue" ")"); do { *((volatile
int*)__null) = 529; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
529 "transaction not queued but in queue")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(chan->mConnecting == CONNECTING_QUEUED)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(chan->mConnecting == CONNECTING_QUEUED))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("chan->mConnecting == CONNECTING_QUEUED"
" (" "transaction not queued but in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED"
") (" "transaction not queued but in queue" ")"); do { *((volatile
int*)__null) = 529; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
530 LOG(("WebSocket: ConnectNext: found channel [this=%p] in queue", chan))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: ConnectNext: found channel [this=%p] in queue"
, chan); } } while (0)
;
531
532 mFailures.DelayOrBegin(chan);
533 }
534 }
535
536 void RemoveFromQueue(WebSocketChannel* aChannel) {
537 LOG(("Websocket: RemoveFromQueue: [this=%p]", aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: RemoveFromQueue: [this=%p]"
, aChannel); } } while (0)
;
538 int32_t index = IndexOf(aChannel);
539 MOZ_ASSERT(index >= 0, "connection to remove not in queue")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index >= 0))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("index >= 0" " ("
"connection to remove not in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index >= 0"
") (" "connection to remove not in queue" ")"); do { *((volatile
int*)__null) = 539; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
540 if (index >= 0) {
541 mQueue.RemoveElementAt(index);
542 }
543 }
544
545 int32_t IndexOf(nsCString& aAddress, nsCString& aOriginSuffix) {
546 for (uint32_t i = 0; i < mQueue.Length(); i++) {
547 bool isPartitioned = StaticPrefs::privacy_partition_network_state() ||
548 StaticPrefs::privacy_firstparty_isolate();
549 if (aAddress == (mQueue[i])->mAddress &&
550 (!isPartitioned || aOriginSuffix == (mQueue[i])->mOriginSuffix)) {
551 return i;
552 }
553 }
554 return -1;
555 }
556
557 int32_t IndexOf(WebSocketChannel* aChannel) {
558 for (uint32_t i = 0; i < mQueue.Length(); i++) {
559 if (aChannel == (mQueue[i])->mChannel) return i;
560 }
561 return -1;
562 }
563
564 // Returns the index of the first entry that failed, or else the last entry if
565 // none found
566 uint32_t IndexOfFirstFailure() {
567 for (uint32_t i = 0; i < mQueue.Length(); i++) {
568 if (mQueue[i]->mFailed) return i;
569 }
570 return mQueue.Length();
571 }
572
573 // SessionCount might be decremented from the main or the socket
574 // thread, so manage it with atomic counters
575 Atomic<int32_t> mSessionCount;
576
577 // Queue for websockets that have not completed connecting yet.
578 // The first nsOpenConn with a given address will be either be
579 // CONNECTING_IN_PROGRESS or CONNECTING_DELAYED. Later ones with the same
580 // hostname must be CONNECTING_QUEUED.
581 //
582 // We could hash hostnames instead of using a single big vector here, but the
583 // dataset is expected to be small.
584 nsTArray<UniquePtr<nsOpenConn>> mQueue;
585
586 FailDelayManager mFailures;
587
588 static nsWSAdmissionManager* sManager MOZ_GUARDED_BY(sLock)__attribute__((guarded_by(sLock)));
589 static StaticMutex sLock;
590};
591
592nsWSAdmissionManager* nsWSAdmissionManager::sManager;
593StaticMutex nsWSAdmissionManager::sLock;
594
595//-----------------------------------------------------------------------------
596// CallOnMessageAvailable
597//-----------------------------------------------------------------------------
598
599class CallOnMessageAvailable final : public Runnable {
600 public:
601 CallOnMessageAvailable(WebSocketChannel* aChannel, nsACString& aData,
602 int32_t aLen)
603 : Runnable("net::CallOnMessageAvailable"),
604 mChannel(aChannel),
605 mListenerMT(aChannel->mListenerMT),
606 mData(aData),
607 mLen(aLen) {}
608
609 NS_IMETHODvirtual nsresult Run() override {
610 MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 610; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
611
612 if (mListenerMT) {
613 nsresult rv;
614 if (mLen < 0) {
615 rv = mListenerMT->mListener->OnMessageAvailable(mListenerMT->mContext,
616 mData);
617 } else {
618 rv = mListenerMT->mListener->OnBinaryMessageAvailable(
619 mListenerMT->mContext, mData);
620 }
621 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
622 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable "
"failed with 0x%08" "x", static_cast<uint32_t>(rv)); }
} while (0)
623 ("OnMessageAvailable or OnBinaryMessageAvailable "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable "
"failed with 0x%08" "x", static_cast<uint32_t>(rv)); }
} while (0)
624 "failed with 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable "
"failed with 0x%08" "x", static_cast<uint32_t>(rv)); }
} while (0)
625 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable "
"failed with 0x%08" "x", static_cast<uint32_t>(rv)); }
} while (0)
;
626 }
627 }
628
629 return NS_OK;
630 }
631
632 private:
633 ~CallOnMessageAvailable() = default;
634
635 RefPtr<WebSocketChannel> mChannel;
636 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
637 nsCString mData;
638 int32_t mLen;
639};
640
641//-----------------------------------------------------------------------------
642// CallOnStop
643//-----------------------------------------------------------------------------
644
645class CallOnStop final : public Runnable {
646 public:
647 CallOnStop(WebSocketChannel* aChannel, nsresult aReason)
648 : Runnable("net::CallOnStop"),
649 mChannel(aChannel),
650 mListenerMT(mChannel->mListenerMT),
651 mReason(aReason) {}
652
653 NS_IMETHODvirtual nsresult Run() override {
654 MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 654; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
655
656 if (mListenerMT) {
657 nsresult rv =
658 mListenerMT->mListener->OnStop(mListenerMT->mContext, mReason);
659 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
660 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop "
"OnStop failed (%08" "x" ")\n", static_cast<uint32_t>(
rv)); } } while (0)
661 ("WebSocketChannel::CallOnStop "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop "
"OnStop failed (%08" "x" ")\n", static_cast<uint32_t>(
rv)); } } while (0)
662 "OnStop failed (%08" PRIx32 ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop "
"OnStop failed (%08" "x" ")\n", static_cast<uint32_t>(
rv)); } } while (0)
663 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop "
"OnStop failed (%08" "x" ")\n", static_cast<uint32_t>(
rv)); } } while (0)
;
664 }
665 mChannel->mListenerMT = nullptr;
666 }
667
668 return NS_OK;
669 }
670
671 private:
672 ~CallOnStop() = default;
673
674 RefPtr<WebSocketChannel> mChannel;
675 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
676 nsresult mReason;
677};
678
679//-----------------------------------------------------------------------------
680// CallOnServerClose
681//-----------------------------------------------------------------------------
682
683class CallOnServerClose final : public Runnable {
684 public:
685 CallOnServerClose(WebSocketChannel* aChannel, uint16_t aCode,
686 nsACString& aReason)
687 : Runnable("net::CallOnServerClose"),
688 mChannel(aChannel),
689 mListenerMT(mChannel->mListenerMT),
690 mCode(aCode),
691 mReason(aReason) {}
692
693 NS_IMETHODvirtual nsresult Run() override {
694 MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
695
696 if (mListenerMT) {
697 nsresult rv = mListenerMT->mListener->OnServerClose(mListenerMT->mContext,
698 mCode, mReason);
699 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
700 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose "
"OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t
>(rv)); } } while (0)
701 ("WebSocketChannel::CallOnServerClose "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose "
"OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t
>(rv)); } } while (0)
702 "OnServerClose failed (%08" PRIx32 ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose "
"OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t
>(rv)); } } while (0)
703 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose "
"OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t
>(rv)); } } while (0)
;
704 }
705 }
706 return NS_OK;
707 }
708
709 private:
710 ~CallOnServerClose() = default;
711
712 RefPtr<WebSocketChannel> mChannel;
713 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
714 uint16_t mCode;
715 nsCString mReason;
716};
717
718//-----------------------------------------------------------------------------
719// CallAcknowledge
720//-----------------------------------------------------------------------------
721
722class CallAcknowledge final : public Runnable {
723 public:
724 CallAcknowledge(WebSocketChannel* aChannel, uint32_t aSize)
725 : Runnable("net::CallAcknowledge"),
726 mChannel(aChannel),
727 mListenerMT(mChannel->mListenerMT),
728 mSize(aSize) {}
729
730 NS_IMETHODvirtual nsresult Run() override {
731 MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
732
733 LOG(("WebSocketChannel::CallAcknowledge: Size %u\n", mSize))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Size %u\n"
, mSize); } } while (0)
;
734 if (mListenerMT) {
735 nsresult rv =
736 mListenerMT->mListener->OnAcknowledge(mListenerMT->mContext, mSize);
737 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
738 LOG(("WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08"
"x" ")\n", static_cast<uint32_t>(rv)); } } while (0)
739 ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08"
"x" ")\n", static_cast<uint32_t>(rv)); } } while (0)
740 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08"
"x" ")\n", static_cast<uint32_t>(rv)); } } while (0)
;
741 }
742 }
743 return NS_OK;
744 }
745
746 private:
747 ~CallAcknowledge() = default;
748
749 RefPtr<WebSocketChannel> mChannel;
750 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
751 uint32_t mSize;
752};
753
754//-----------------------------------------------------------------------------
755// CallOnTransportAvailable
756//-----------------------------------------------------------------------------
757
758class CallOnTransportAvailable final : public Runnable {
759 public:
760 CallOnTransportAvailable(WebSocketChannel* aChannel,
761 nsISocketTransport* aTransport,
762 nsIAsyncInputStream* aSocketIn,
763 nsIAsyncOutputStream* aSocketOut)
764 : Runnable("net::CallOnTransportAvailble"),
765 mChannel(aChannel),
766 mTransport(aTransport),
767 mSocketIn(aSocketIn),
768 mSocketOut(aSocketOut) {}
769
770 NS_IMETHODvirtual nsresult Run() override {
771 LOG(("WebSocketChannel::CallOnTransportAvailable %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnTransportAvailable %p\n"
, this); } } while (0)
;
772 return mChannel->OnTransportAvailable(mTransport, mSocketIn, mSocketOut);
773 }
774
775 private:
776 ~CallOnTransportAvailable() = default;
777
778 RefPtr<WebSocketChannel> mChannel;
779 nsCOMPtr<nsISocketTransport> mTransport;
780 nsCOMPtr<nsIAsyncInputStream> mSocketIn;
781 nsCOMPtr<nsIAsyncOutputStream> mSocketOut;
782};
783
784//-----------------------------------------------------------------------------
785// PMCECompression
786//-----------------------------------------------------------------------------
787
788class PMCECompression {
789 public:
790 PMCECompression(bool aNoContextTakeover, int32_t aLocalMaxWindowBits,
791 int32_t aRemoteMaxWindowBits)
792 : mActive(false),
793 mNoContextTakeover(aNoContextTakeover),
794 mResetDeflater(false),
795 mMessageDeflated(false) {
796 this->mDeflater.next_in = nullptr;
797 this->mDeflater.avail_in = 0;
798 this->mDeflater.total_in = 0;
799 this->mDeflater.next_out = nullptr;
800 this->mDeflater.avail_out = 0;
801 this->mDeflater.total_out = 0;
802 this->mDeflater.msg = nullptr;
803 this->mDeflater.state = nullptr;
804 this->mDeflater.data_type = 0;
805 this->mDeflater.adler = 0;
806 this->mDeflater.reserved = 0;
807 this->mInflater.next_in = nullptr;
808 this->mInflater.avail_in = 0;
809 this->mInflater.total_in = 0;
810 this->mInflater.next_out = nullptr;
811 this->mInflater.avail_out = 0;
812 this->mInflater.total_out = 0;
813 this->mInflater.msg = nullptr;
814 this->mInflater.state = nullptr;
815 this->mInflater.data_type = 0;
816 this->mInflater.adler = 0;
817 this->mInflater.reserved = 0;
818 MOZ_COUNT_CTOR(PMCECompression)do { static_assert(std::is_class_v<PMCECompression>, "Token '"
"PMCECompression" "' is not a class type."); static_assert(!
std::is_base_of<nsISupports, PMCECompression>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "PMCECompression"
, sizeof(*this)); } while (0)
;
819
820 mDeflater.zalloc = mInflater.zalloc = Z_NULL0;
821 mDeflater.zfree = mInflater.zfree = Z_NULL0;
822 mDeflater.opaque = mInflater.opaque = Z_NULL0;
823
824 if (deflateInit2(&mDeflater, Z_DEFAULT_COMPRESSION, Z_DEFLATED,MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits
),(8), (0), "1.3.1", (int)sizeof(z_stream))
825 -aLocalMaxWindowBits, 8, Z_DEFAULT_STRATEGY)MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits
),(8), (0), "1.3.1", (int)sizeof(z_stream))
== Z_OK0) {
826 if (inflateInit2(&mInflater, -aRemoteMaxWindowBits)MOZ_Z_inflateInit2_((&mInflater), (-aRemoteMaxWindowBits)
, "1.3.1", (int)sizeof(z_stream))
== Z_OK0) {
827 mActive = true;
828 } else {
829 deflateEndMOZ_Z_deflateEnd(&mDeflater);
830 }
831 }
832 }
833
834 ~PMCECompression() {
835 MOZ_COUNT_DTOR(PMCECompression)do { static_assert(std::is_class_v<PMCECompression>, "Token '"
"PMCECompression" "' is not a class type."); static_assert(!
std::is_base_of<nsISupports, PMCECompression>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "PMCECompression"
, sizeof(*this)); } while (0)
;
836
837 if (mActive) {
838 inflateEndMOZ_Z_inflateEnd(&mInflater);
839 deflateEndMOZ_Z_deflateEnd(&mDeflater);
840 }
841 }
842
843 bool Active() { return mActive; }
844
845 void SetMessageDeflated() {
846 MOZ_ASSERT(!mMessageDeflated)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mMessageDeflated)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mMessageDeflated))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mMessageDeflated"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mMessageDeflated"
")"); do { *((volatile int*)__null) = 846; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
847 mMessageDeflated = true;
848 }
849 bool IsMessageDeflated() { return mMessageDeflated; }
850
851 bool UsingContextTakeover() { return !mNoContextTakeover; }
852
853 nsresult Deflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) {
854 if (mResetDeflater || mNoContextTakeover) {
855 if (deflateResetMOZ_Z_deflateReset(&mDeflater) != Z_OK0) {
856 return NS_ERROR_UNEXPECTED;
857 }
858 mResetDeflater = false;
859 }
860
861 mDeflater.avail_out = kBufferLen;
862 mDeflater.next_out = mBuffer;
863 mDeflater.avail_in = dataLen;
864 mDeflater.next_in = data;
865
866 while (true) {
867 int zerr = deflateMOZ_Z_deflate(&mDeflater, Z_SYNC_FLUSH2);
868
869 if (zerr != Z_OK0) {
870 mResetDeflater = true;
871 return NS_ERROR_UNEXPECTED;
872 }
873
874 uint32_t deflated = kBufferLen - mDeflater.avail_out;
875 if (deflated > 0) {
876 _retval.Append(reinterpret_cast<char*>(mBuffer), deflated);
877 }
878
879 mDeflater.avail_out = kBufferLen;
880 mDeflater.next_out = mBuffer;
881
882 if (mDeflater.avail_in > 0) {
883 continue; // There is still some data to deflate
884 }
885
886 if (deflated == kBufferLen) {
887 continue; // There was not enough space in the buffer
888 }
889
890 break;
891 }
892
893 if (_retval.Length() < 4) {
894 MOZ_ASSERT(false, "Expected trailing not found in deflated data!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Expected trailing not found in deflated data!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Expected trailing not found in deflated data!" ")"); do { *
((volatile int*)__null) = 894; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
895 mResetDeflater = true;
896 return NS_ERROR_UNEXPECTED;
897 }
898
899 _retval.Truncate(_retval.Length() - 4);
900
901 return NS_OK;
902 }
903
904 nsresult Inflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) {
905 mMessageDeflated = false;
906
907 Bytef trailingData[] = {0x00, 0x00, 0xFF, 0xFF};
908 bool trailingDataUsed = false;
909
910 mInflater.avail_out = kBufferLen;
911 mInflater.next_out = mBuffer;
912 mInflater.avail_in = dataLen;
913 mInflater.next_in = data;
914
915 while (true) {
916 int zerr = inflateMOZ_Z_inflate(&mInflater, Z_NO_FLUSH0);
917
918 if (zerr == Z_STREAM_END1) {
919 Bytef* saveNextIn = mInflater.next_in;
920 uint32_t saveAvailIn = mInflater.avail_in;
921 Bytef* saveNextOut = mInflater.next_out;
922 uint32_t saveAvailOut = mInflater.avail_out;
923
924 inflateResetMOZ_Z_inflateReset(&mInflater);
925
926 mInflater.next_in = saveNextIn;
927 mInflater.avail_in = saveAvailIn;
928 mInflater.next_out = saveNextOut;
929 mInflater.avail_out = saveAvailOut;
930 } else if (zerr != Z_OK0 && zerr != Z_BUF_ERROR(-5)) {
931 return NS_ERROR_INVALID_CONTENT_ENCODING;
932 }
933
934 uint32_t inflated = kBufferLen - mInflater.avail_out;
935 if (inflated > 0) {
936 if (!_retval.Append(reinterpret_cast<char*>(mBuffer), inflated,
937 fallible)) {
938 return NS_ERROR_OUT_OF_MEMORY;
939 }
940 }
941
942 mInflater.avail_out = kBufferLen;
943 mInflater.next_out = mBuffer;
944
945 if (mInflater.avail_in > 0) {
946 continue; // There is still some data to inflate
947 }
948
949 if (inflated == kBufferLen) {
950 continue; // There was not enough space in the buffer
951 }
952
953 if (!trailingDataUsed) {
954 trailingDataUsed = true;
955 mInflater.avail_in = sizeof(trailingData);
956 mInflater.next_in = trailingData;
957 continue;
958 }
959
960 return NS_OK;
961 }
962 }
963
964 private:
965 bool mActive;
966 bool mNoContextTakeover;
967 bool mResetDeflater;
968 bool mMessageDeflated;
969 z_stream mDeflater{};
970 z_stream mInflater{};
971 const static uint32_t kBufferLen = 4096;
972 uint8_t mBuffer[kBufferLen]{0};
973};
974
975//-----------------------------------------------------------------------------
976// OutboundMessage
977//-----------------------------------------------------------------------------
978
979enum WsMsgType {
980 kMsgTypeString = 0,
981 kMsgTypeBinaryString,
982 kMsgTypeStream,
983 kMsgTypePing,
984 kMsgTypePong,
985 kMsgTypeFin
986};
987
988static const char* msgNames[] = {"text", "binaryString", "binaryStream",
989 "ping", "pong", "close"};
990
991class OutboundMessage {
992 public:
993 OutboundMessage(WsMsgType type, const nsACString& str)
994 : mMsg(mozilla::AsVariant(pString(str))),
995 mMsgType(type),
996 mDeflated(false) {
997 MOZ_COUNT_CTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '"
"OutboundMessage" "' is not a class type."); static_assert(!
std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "OutboundMessage"
, sizeof(*this)); } while (0)
;
998 }
999
1000 OutboundMessage(nsIInputStream* stream, uint32_t length)
1001 : mMsg(mozilla::AsVariant(StreamWithLength(stream, length))),
1002 mMsgType(kMsgTypeStream),
1003 mDeflated(false) {
1004 MOZ_COUNT_CTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '"
"OutboundMessage" "' is not a class type."); static_assert(!
std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "OutboundMessage"
, sizeof(*this)); } while (0)
;
1005 }
1006
1007 ~OutboundMessage() {
1008 MOZ_COUNT_DTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '"
"OutboundMessage" "' is not a class type."); static_assert(!
std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "OutboundMessage"
, sizeof(*this)); } while (0)
;
1009 switch (mMsgType) {
1010 case kMsgTypeString:
1011 case kMsgTypeBinaryString:
1012 case kMsgTypePing:
1013 case kMsgTypePong:
1014 break;
1015 case kMsgTypeStream:
1016 // for now this only gets hit if msg deleted w/o being sent
1017 if (mMsg.as<StreamWithLength>().mStream) {
1018 mMsg.as<StreamWithLength>().mStream->Close();
1019 }
1020 break;
1021 case kMsgTypeFin:
1022 break; // do-nothing: avoid compiler warning
1023 }
1024 }
1025
1026 WsMsgType GetMsgType() const { return mMsgType; }
1027 int32_t Length() {
1028 if (mMsg.is<pString>()) {
1029 return mMsg.as<pString>().mValue.Length();
1030 }
1031
1032 return mMsg.as<StreamWithLength>().mLength;
1033 }
1034 int32_t OrigLength() {
1035 if (mMsg.is<pString>()) {
1036 pString& ref = mMsg.as<pString>();
1037 return mDeflated ? ref.mOrigValue.Length() : ref.mValue.Length();
1038 }
1039
1040 return mMsg.as<StreamWithLength>().mLength;
1041 }
1042
1043 uint8_t* BeginWriting() {
1044 MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1045; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1045 "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1045; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1046 if (!mMsg.as<pString>().mValue.IsVoid()) {
1047 return (uint8_t*)mMsg.as<pString>().mValue.BeginWriting();
1048 }
1049 return nullptr;
1050 }
1051
1052 uint8_t* BeginReading() {
1053 MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1054; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1054 "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1054; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1055 if (!mMsg.as<pString>().mValue.IsVoid()) {
1056 return (uint8_t*)mMsg.as<pString>().mValue.BeginReading();
1057 }
1058 return nullptr;
1059 }
1060
1061 uint8_t* BeginOrigReading() {
1062 MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1063 "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1063; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1064 if (!mDeflated) return BeginReading();
1065 if (!mMsg.as<pString>().mOrigValue.IsVoid()) {
1066 return (uint8_t*)mMsg.as<pString>().mOrigValue.BeginReading();
1067 }
1068 return nullptr;
1069 }
1070
1071 nsresult ConvertStreamToString() {
1072 MOZ_ASSERT(mMsgType == kMsgTypeStream, "Not a stream!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType == kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType == kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType == kMsgTypeStream"
" (" "Not a stream!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType == kMsgTypeStream"
") (" "Not a stream!" ")"); do { *((volatile int*)__null) = 1072
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1073 nsAutoCString temp;
1074 {
1075 StreamWithLength& ref = mMsg.as<StreamWithLength>();
1076 nsresult rv = NS_ReadInputStreamToString(ref.mStream, temp, ref.mLength);
1077
1078 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/protocol/websocket/WebSocketChannel.cpp"
, 1078); return rv; } } while (false)
;
1079 if (temp.Length() != ref.mLength) {
1080 return NS_ERROR_UNEXPECTED;
1081 }
1082 ref.mStream->Close();
1083 }
1084
1085 mMsg = mozilla::AsVariant(pString(temp));
1086 mMsgType = kMsgTypeBinaryString;
1087
1088 return NS_OK;
1089 }
1090
1091 bool DeflatePayload(PMCECompression* aCompressor) {
1092 MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1093; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1093 "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream"
" (" "Stream should have been converted to string by now" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1093; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1094 MOZ_ASSERT(!mDeflated)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeflated)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDeflated))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mDeflated", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDeflated"
")"); do { *((volatile int*)__null) = 1094; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1095
1096 nsresult rv;
1097 pString& ref = mMsg.as<pString>();
1098 if (ref.mValue.Length() == 0) {
1099 // Empty message
1100 return false;
1101 }
1102
1103 nsAutoCString temp;
1104 rv = aCompressor->Deflate(BeginReading(), ref.mValue.Length(), temp);
1105 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1106 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed "
"[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } }
while (0)
1107 ("WebSocketChannel::OutboundMessage: Deflating payload failed "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed "
"[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } }
while (0)
1108 "[rv=0x%08" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed "
"[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } }
while (0)
1109 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed "
"[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } }
while (0)
;
1110 return false;
1111 }
1112
1113 if (!aCompressor->UsingContextTakeover() &&
1114 temp.Length() > ref.mValue.Length()) {
1115 // When "<local>_no_context_takeover" was negotiated, do not send deflated
1116 // payload if it's larger that the original one. OTOH, it makes sense
1117 // to send the larger deflated payload when the sliding window is not
1118 // reset between messages because if we would skip some deflated block
1119 // we would need to empty the sliding window which could affect the
1120 // compression of the subsequent messages.
1121 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the "
"deflated payload is larger than the original one [deflated=%zd, "
"original=%zd]", temp.Length(), ref.mValue.Length()); } } while
(0)
1122 ("WebSocketChannel::OutboundMessage: Not deflating message since the "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the "
"deflated payload is larger than the original one [deflated=%zd, "
"original=%zd]", temp.Length(), ref.mValue.Length()); } } while
(0)
1123 "deflated payload is larger than the original one [deflated=%zd, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the "
"deflated payload is larger than the original one [deflated=%zd, "
"original=%zd]", temp.Length(), ref.mValue.Length()); } } while
(0)
1124 "original=%zd]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the "
"deflated payload is larger than the original one [deflated=%zd, "
"original=%zd]", temp.Length(), ref.mValue.Length()); } } while
(0)
1125 temp.Length(), ref.mValue.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the "
"deflated payload is larger than the original one [deflated=%zd, "
"original=%zd]", temp.Length(), ref.mValue.Length()); } } while
(0)
;
1126 return false;
1127 }
1128
1129 mDeflated = true;
1130 mMsg.as<pString>().mOrigValue = mMsg.as<pString>().mValue;
1131 mMsg.as<pString>().mValue = temp;
1132 return true;
1133 }
1134
1135 private:
1136 struct pString {
1137 nsCString mValue;
1138 nsCString mOrigValue;
1139 explicit pString(const nsACString& value)
1140 : mValue(value), mOrigValue(VoidCString()) {}
1141 };
1142 struct StreamWithLength {
1143 nsCOMPtr<nsIInputStream> mStream;
1144 uint32_t mLength;
1145 explicit StreamWithLength(nsIInputStream* stream, uint32_t Length)
1146 : mStream(stream), mLength(Length) {}
1147 };
1148 mozilla::Variant<pString, StreamWithLength> mMsg;
1149 WsMsgType mMsgType;
1150 bool mDeflated;
1151};
1152
1153//-----------------------------------------------------------------------------
1154// OutboundEnqueuer
1155//-----------------------------------------------------------------------------
1156
1157class OutboundEnqueuer final : public Runnable {
1158 public:
1159 OutboundEnqueuer(WebSocketChannel* aChannel, OutboundMessage* aMsg)
1160 : Runnable("OutboundEnquerer"), mChannel(aChannel), mMessage(aMsg) {}
1161
1162 NS_IMETHODvirtual nsresult Run() override {
1163 mChannel->EnqueueOutgoingMessage(mChannel->mOutgoingMessages, mMessage);
1164 return NS_OK;
1165 }
1166
1167 private:
1168 ~OutboundEnqueuer() = default;
1169
1170 RefPtr<WebSocketChannel> mChannel;
1171 OutboundMessage* mMessage;
1172};
1173
1174//-----------------------------------------------------------------------------
1175// WebSocketChannel
1176//-----------------------------------------------------------------------------
1177
1178WebSocketChannel::WebSocketChannel()
1179 : mPort(0),
1180 mCloseTimeout(20000),
1181 mOpenTimeout(20000),
1182 mConnecting(NOT_CONNECTING),
1183 mMaxConcurrentConnections(200),
1184 mInnerWindowID(0),
1185 mGotUpgradeOK(0),
1186 mRecvdHttpUpgradeTransport(0),
1187 mPingOutstanding(0),
1188 mReleaseOnTransmit(0),
1189 mDataStarted(false),
1190 mRequestedClose(false),
1191 mClientClosed(false),
1192 mServerClosed(false),
1193 mStopped(false),
1194 mCalledOnStop(false),
1195 mTCPClosed(false),
1196 mOpenedHttpChannel(false),
1197 mIncrementedSessionCount(false),
1198 mDecrementedSessionCount(false),
1199 mMaxMessageSize(INT32_MAX(2147483647)),
1200 mStopOnClose(NS_OK),
1201 mServerCloseCode(CLOSE_ABNORMAL),
1202 mScriptCloseCode(0),
1203 mFragmentOpcode(nsIWebSocketFrame::OPCODE_CONTINUATION),
1204 mFragmentAccumulator(0),
1205 mBuffered(0),
1206 mBufferSize(kIncomingBufferInitialSize),
1207 mCurrentOut(nullptr),
1208 mCurrentOutSent(0),
1209 mHdrOutToSend(0),
1210 mHdrOut(nullptr),
1211 mCompressorMutex("WebSocketChannel::mCompressorMutex"),
1212 mDynamicOutputSize(0),
1213 mDynamicOutput(nullptr),
1214 mPrivateBrowsing(false),
1215 mConnectionLogService(nullptr),
1216 mMutex("WebSocketChannel::mMutex") {
1217 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
1217; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
1218
1219 LOG(("WebSocketChannel::WebSocketChannel() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::WebSocketChannel() %p\n"
, this); } } while (0)
;
1220
1221 nsWSAdmissionManager::Init();
1222
1223 mFramePtr = mBuffer = static_cast<uint8_t*>(moz_xmalloc(mBufferSize));
1224
1225 nsresult rv;
1226 mConnectionLogService = mozilla::components::Dashboard::Service(&rv);
1227 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) LOG(("Failed to initiate dashboard service."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; 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 initiate dashboard service."
); } } while (0)
;
1228
1229 mService = WebSocketEventService::GetOrCreate();
1230}
1231
1232WebSocketChannel::~WebSocketChannel() {
1233 LOG(("WebSocketChannel::~WebSocketChannel() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::~WebSocketChannel() %p\n"
, this); } } while (0)
;
1234
1235 if (mWasOpened) {
1236 MOZ_ASSERT(mCalledOnStop, "WebSocket was opened but OnStop was not called")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCalledOnStop)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCalledOnStop))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mCalledOnStop" " ("
"WebSocket was opened but OnStop was not called" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCalledOnStop"
") (" "WebSocket was opened but OnStop was not called" ")");
do { *((volatile int*)__null) = 1236; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1237 MOZ_ASSERT(mStopped, "WebSocket was opened but never stopped")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mStopped" " (" "WebSocket was opened but never stopped"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") ("
"WebSocket was opened but never stopped" ")"); do { *((volatile
int*)__null) = 1237; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1238 }
1239 MOZ_ASSERT(!mCancelable, "DNS/Proxy Request still alive at destruction")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCancelable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mCancelable" " ("
"DNS/Proxy Request still alive at destruction" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable"
") (" "DNS/Proxy Request still alive at destruction" ")"); do
{ *((volatile int*)__null) = 1239; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1240 MOZ_ASSERT(!mConnecting, "Should not be connecting in destructor")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mConnecting)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mConnecting))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mConnecting" " ("
"Should not be connecting in destructor" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnecting"
") (" "Should not be connecting in destructor" ")"); do { *(
(volatile int*)__null) = 1240; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1241
1242 free(mBuffer);
1243 free(mDynamicOutput);
1244 delete mCurrentOut;
1245
1246 while ((mCurrentOut = mOutgoingPingMessages.PopFront())) {
1247 delete mCurrentOut;
1248 }
1249 while ((mCurrentOut = mOutgoingPongMessages.PopFront())) {
1250 delete mCurrentOut;
1251 }
1252 while ((mCurrentOut = mOutgoingMessages.PopFront())) {
1253 delete mCurrentOut;
1254 }
1255
1256 mListenerMT = nullptr;
1257
1258 NS_ReleaseOnMainThread("WebSocketChannel::mService", mService.forget());
1259}
1260
1261NS_IMETHODIMPnsresult
1262WebSocketChannel::Observe(nsISupports* subject, const char* topic,
1263 const char16_t* data) {
1264 LOG(("WebSocketChannel::Observe [topic=\"%s\"]\n", topic))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Observe [topic=\"%s\"]\n"
, topic); } } while (0)
;
1265
1266 if (strcmp(topic, NS_NETWORK_LINK_TOPIC"network:link-status-changed") == 0) {
1267 nsCString converted = NS_ConvertUTF16toUTF8(data);
1268 const char* state = converted.get();
1269
1270 if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED"changed") == 0) {
1271 LOG(("WebSocket: received network CHANGED event"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: received network CHANGED event"
); } } while (0)
;
1272
1273 if (!mIOThread) {
1274 // there has not been an asyncopen yet on the object and then we need
1275 // no ping.
1276 LOG(("WebSocket: early object, no ping needed"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: early object, no ping needed"
); } } while (0)
;
1277 } else {
1278 mIOThread->Dispatch(
1279 NewRunnableMethod("net::WebSocketChannel::OnNetworkChanged", this,
1280 &WebSocketChannel::OnNetworkChanged),
1281 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1282 }
1283 }
1284 }
1285
1286 return NS_OK;
1287}
1288
1289nsresult WebSocketChannel::OnNetworkChanged() {
1290 if (!mDataStarted) {
1291 LOG(("WebSocket: data not started yet, no ping needed"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: data not started yet, no ping needed"
); } } while (0)
;
1292 return NS_OK;
1293 }
1294
1295 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 1295; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1296
1297 LOG(("WebSocketChannel::OnNetworkChanged() - on socket thread %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnNetworkChanged() - on socket thread %p"
, this); } } while (0)
;
1298
1299 if (mPingOutstanding) {
1300 // If there's an outstanding ping that's expected to get a pong back
1301 // we let that do its thing.
1302 LOG(("WebSocket: pong already pending"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: pong already pending"
); } } while (0)
;
1303 return NS_OK;
1304 }
1305
1306 if (mPingForced) {
1307 // avoid more than one
1308 LOG(("WebSocket: forced ping timer already fired"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: forced ping timer already fired"
); } } while (0)
;
1309 return NS_OK;
1310 }
1311
1312 LOG(("nsWebSocketChannel:: Generating Ping as network changed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Generating Ping as network changed\n"
); } } while (0)
;
1313
1314 if (!mPingTimer) {
1315 // The ping timer is only conditionally running already. If it wasn't
1316 // already created do it here.
1317 mPingTimer = NS_NewTimer();
1318 if (!mPingTimer) {
1319 LOG(("WebSocket: unable to create ping timer!"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: unable to create ping timer!"
); } } while (0)
;
1320 NS_WARNING("unable to create ping timer!")NS_DebugBreak(NS_DEBUG_WARNING, "unable to create ping timer!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1320)
;
1321 return NS_ERROR_OUT_OF_MEMORY;
1322 }
1323 }
1324 // Trigger the ping timeout asap to fire off a new ping. Wait just
1325 // a little bit to better avoid multi-triggers.
1326 mPingForced = true;
1327 mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT);
1328
1329 return NS_OK;
1330}
1331
1332void WebSocketChannel::Shutdown() { nsWSAdmissionManager::Shutdown(); }
1333
1334void WebSocketChannel::GetEffectiveURL(nsAString& aEffectiveURL) const {
1335 aEffectiveURL = mEffectiveURL;
1336}
1337
1338bool WebSocketChannel::IsEncrypted() const { return mEncrypted; }
1339
1340void WebSocketChannel::BeginOpen(bool aCalledFromAdmissionManager) {
1341 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
1341; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
1342
1343 LOG(("WebSocketChannel::BeginOpen() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpen() %p\n"
, this); } } while (0)
;
1344
1345 // Important that we set CONNECTING_IN_PROGRESS before any call to
1346 // AbortSession here: ensures that any remaining queued connection(s) are
1347 // scheduled in OnStopSession
1348 LOG(("Websocket: changing state to CONNECTING_IN_PROGRESS"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to CONNECTING_IN_PROGRESS"
); } } while (0)
;
1349 mConnecting = CONNECTING_IN_PROGRESS;
1350
1351 if (aCalledFromAdmissionManager) {
1352 // When called from nsWSAdmissionManager post an event to avoid potential
1353 // re-entering of nsWSAdmissionManager and its lock.
1354 NS_DispatchToMainThread(
1355 NewRunnableMethod("net::WebSocketChannel::BeginOpenInternal", this,
1356 &WebSocketChannel::BeginOpenInternal),
1357 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1358 } else {
1359 BeginOpenInternal();
1360 }
1361}
1362
1363// MainThread
1364void WebSocketChannel::BeginOpenInternal() {
1365 LOG(("WebSocketChannel::BeginOpenInternal() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal() %p\n"
, this); } } while (0)
;
1366 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
1366; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
1367
1368 nsresult rv;
1369
1370 if (mRedirectCallback) {
1371 LOG(("WebSocketChannel::BeginOpenInternal: Resuming Redirect\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: Resuming Redirect\n"
); } } while (0)
;
1372 rv = mRedirectCallback->OnRedirectVerifyCallback(NS_OK);
1373 mRedirectCallback = nullptr;
1374 return;
1375 }
1376
1377 nsCOMPtr<nsIChannel> localChannel = do_QueryInterface(mChannel, &rv);
1378 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1379 LOG(("WebSocketChannel::BeginOpenInternal: cannot async open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot async open\n"
); } } while (0)
;
1380 AbortSession(NS_ERROR_UNEXPECTED);
1381 return;
1382 }
1383
1384 rv = localChannel->AsyncOpen(this);
1385
1386 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1387 LOG(("WebSocketChannel::BeginOpenInternal: cannot async open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot async open\n"
); } } while (0)
;
1388 AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED);
1389 return;
1390 }
1391 mOpenedHttpChannel = true;
1392
1393 rv = NS_NewTimerWithCallback(getter_AddRefs(mOpenTimer), this, mOpenTimeout,
1394 nsITimer::TYPE_ONE_SHOT);
1395 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1396 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open "
"timer\n"); } } while (0)
1397 ("WebSocketChannel::BeginOpenInternal: cannot initialize open "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open "
"timer\n"); } } while (0)
1398 "timer\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open "
"timer\n"); } } while (0)
;
1399 AbortSession(NS_ERROR_UNEXPECTED);
1400 return;
1401 }
1402}
1403
1404bool WebSocketChannel::IsPersistentFramePtr() {
1405 return (mFramePtr >= mBuffer && mFramePtr < mBuffer + mBufferSize);
1406}
1407
1408// Extends the internal buffer by count and returns the total
1409// amount of data available for read
1410//
1411// Accumulated fragment size is passed in instead of using the member
1412// variable beacuse when transitioning from the stack to the persistent
1413// read buffer we want to explicitly include them in the buffer instead
1414// of as already existing data.
1415bool WebSocketChannel::UpdateReadBuffer(uint8_t* buffer, uint32_t count,
1416 uint32_t accumulatedFragments,
1417 uint32_t* available) {
1418 LOG(("WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n", this, buffer,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n"
, this, buffer, count); } } while (0)
1419 count))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n"
, this, buffer, count); } } while (0)
;
1420
1421 if (!mBuffered) mFramePtr = mBuffer;
1422
1423 MOZ_ASSERT(IsPersistentFramePtr(), "update read buffer bad mFramePtr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPersistentFramePtr())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPersistentFramePtr()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsPersistentFramePtr()"
" (" "update read buffer bad mFramePtr" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPersistentFramePtr()"
") (" "update read buffer bad mFramePtr" ")"); do { *((volatile
int*)__null) = 1423; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1424 MOZ_ASSERT(mFramePtr - accumulatedFragments >= mBuffer,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFramePtr - accumulatedFragments >= mBuffer)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mFramePtr - accumulatedFragments >= mBuffer))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("mFramePtr - accumulatedFragments >= mBuffer"
" (" "reserved FramePtr bad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer"
") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null
) = 1425; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
1425 "reserved FramePtr bad")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFramePtr - accumulatedFragments >= mBuffer)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mFramePtr - accumulatedFragments >= mBuffer))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("mFramePtr - accumulatedFragments >= mBuffer"
" (" "reserved FramePtr bad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer"
") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null
) = 1425; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1426
1427 if (mBuffered + count <= mBufferSize) {
1428 // append to existing buffer
1429 LOG(("WebSocketChannel: update read buffer absorbed %u\n", count))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer absorbed %u\n"
, count); } } while (0)
;
1430 } else if (mBuffered + count - (mFramePtr - accumulatedFragments - mBuffer) <=
1431 mBufferSize) {
1432 // make room in existing buffer by shifting unused data to start
1433 mBuffered -= (mFramePtr - mBuffer - accumulatedFragments);
1434 LOG(("WebSocketChannel: update read buffer shifted %u\n", mBuffered))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer shifted %u\n"
, mBuffered); } } while (0)
;
1435 ::memmove(mBuffer, mFramePtr - accumulatedFragments, mBuffered);
1436 mFramePtr = mBuffer + accumulatedFragments;
1437 } else {
1438 // existing buffer is not sufficient, extend it
1439 mBufferSize += count + 8192 + mBufferSize / 3;
1440 LOG(("WebSocketChannel: update read buffer extended to %u\n", mBufferSize))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer extended to %u\n"
, mBufferSize); } } while (0)
;
1441 uint8_t* old = mBuffer;
1442 mBuffer = (uint8_t*)realloc(mBuffer, mBufferSize);
1443 if (!mBuffer) {
1444 mBuffer = old;
1445 return false;
1446 }
1447 mFramePtr = mBuffer + (mFramePtr - old);
1448 }
1449
1450 ::memcpy(mBuffer + mBuffered, buffer, count);
1451 mBuffered += count;
1452
1453 if (available) *available = mBuffered - (mFramePtr - mBuffer);
1454
1455 return true;
1456}
1457
1458nsresult WebSocketChannel::ProcessInput(uint8_t* buffer, uint32_t count) {
1459 LOG(("WebSocketChannel::ProcessInput %p [%d %d]\n", this, count, mBuffered))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput %p [%d %d]\n"
, this, count, mBuffered); } } while (0)
;
1460 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 1460; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1461
1462 nsresult rv;
1463
1464 // The purpose of ping/pong is to actively probe the peer so that an
1465 // unreachable peer is not mistaken for a period of idleness. This
1466 // implementation accepts any application level read activity as a sign of
1467 // life, it does not necessarily have to be a pong.
1468 ResetPingTimer();
1469
1470 uint32_t avail;
1471
1472 if (!mBuffered) {
1473 // Most of the time we can process right off the stack buffer without
1474 // having to accumulate anything
1475 mFramePtr = buffer;
1476 avail = count;
1477 } else {
1478 if (!UpdateReadBuffer(buffer, count, mFragmentAccumulator, &avail)) {
1479 return NS_ERROR_FILE_TOO_BIG;
1480 }
1481 }
1482
1483 uint8_t* payload;
1484 uint32_t totalAvail = avail;
1485
1486 while (avail >= 2) {
1487 int64_t payloadLength64 = mFramePtr[1] & kPayloadLengthBitsMask;
1488 uint8_t finBit = mFramePtr[0] & kFinalFragBit;
1489 uint8_t rsvBits = mFramePtr[0] & kRsvBitsMask;
1490 uint8_t rsvBit1 = mFramePtr[0] & kRsv1Bit;
1491 uint8_t rsvBit2 = mFramePtr[0] & kRsv2Bit;
1492 uint8_t rsvBit3 = mFramePtr[0] & kRsv3Bit;
1493 uint8_t opcode = mFramePtr[0] & kOpcodeBitsMask;
1494 uint8_t maskBit = mFramePtr[1] & kMaskBit;
1495 uint32_t mask = 0;
1496
1497 uint32_t framingLength = 2;
1498 if (maskBit) framingLength += 4;
1499
1500 if (payloadLength64 < 126) {
1501 if (avail < framingLength) break;
1502 } else if (payloadLength64 == 126) {
1503 // 16 bit length field
1504 framingLength += 2;
1505 if (avail < framingLength) break;
1506
1507 payloadLength64 = mFramePtr[2] << 8 | mFramePtr[3];
1508
1509 if (payloadLength64 < 126) {
1510 // Section 5.2 says that the minimal number of bytes MUST
1511 // be used to encode the length in all cases
1512 LOG(("WebSocketChannel:: non-minimal-encoded payload length"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: non-minimal-encoded payload length"
); } } while (0)
;
1513 return NS_ERROR_ILLEGAL_VALUE;
1514 }
1515
1516 } else {
1517 // 64 bit length
1518 framingLength += 8;
1519 if (avail < framingLength) break;
1520
1521 if (mFramePtr[2] & 0x80) {
1522 // Section 4.2 says that the most significant bit MUST be
1523 // 0. (i.e. this is really a 63 bit value)
1524 LOG(("WebSocketChannel:: high bit of 64 bit length set"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: high bit of 64 bit length set"
); } } while (0)
;
1525 return NS_ERROR_ILLEGAL_VALUE;
1526 }
1527
1528 // copy this in case it is unaligned
1529 payloadLength64 = NetworkEndian::readInt64(mFramePtr + 2);
1530
1531 if (payloadLength64 <= 0xffff) {
1532 // Section 5.2 says that the minimal number of bytes MUST
1533 // be used to encode the length in all cases
1534 LOG(("WebSocketChannel:: non-minimal-encoded payload length"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: non-minimal-encoded payload length"
); } } while (0)
;
1535 return NS_ERROR_ILLEGAL_VALUE;
1536 }
1537 }
1538
1539 payload = mFramePtr + framingLength;
1540 avail -= framingLength;
1541
1542 LOG(("WebSocketChannel::ProcessInput: payload %" PRId64 " avail %" PRIu32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %"
"l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while
(0)
1543 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %"
"l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while
(0)
1544 payloadLength64, avail))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %"
"l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while
(0)
;
1545
1546 CheckedInt<int64_t> payloadLengthChecked(payloadLength64);
1547 payloadLengthChecked += mFragmentAccumulator;
1548 if (!payloadLengthChecked.isValid() ||
1549 payloadLengthChecked.value() > mMaxMessageSize) {
1550 return NS_ERROR_FILE_TOO_BIG;
1551 }
1552
1553 uint32_t payloadLength = static_cast<uint32_t>(payloadLength64);
1554
1555 if (avail < payloadLength) break;
1556
1557 LOG(("WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n"
, opcode); } } while (0)
1558 opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n"
, opcode); } } while (0)
;
1559
1560 if (!maskBit && mIsServerSide) {
1561 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received "
"from client\n"); } } while (0)
1562 ("WebSocketChannel::ProcessInput: unmasked frame received "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received "
"from client\n"); } } while (0)
1563 "from client\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received "
"from client\n"); } } while (0)
;
1564 return NS_ERROR_ILLEGAL_VALUE;
1565 }
1566
1567 if (maskBit) {
1568 if (!mIsServerSide) {
1569 // The server should not be allowed to send masked frames to clients.
1570 // But we've been allowing it for some time, so this should be
1571 // deprecated with care.
1572 LOG(("WebSocketChannel:: Client RECEIVING masked frame."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Client RECEIVING masked frame."
); } } while (0)
;
1573 }
1574
1575 mask = NetworkEndian::readUint32(payload - 4);
1576 }
1577
1578 if (mask) {
1579 ApplyMask(mask, payload, payloadLength);
1580 } else if (mIsServerSide) {
1581 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received"
"from client\n"); } } while (0)
1582 ("WebSocketChannel::ProcessInput: masked frame with mask 0 received"do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received"
"from client\n"); } } while (0)
1583 "from client\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received"
"from client\n"); } } while (0)
;
1584 return NS_ERROR_ILLEGAL_VALUE;
1585 }
1586
1587 // Control codes are required to have the fin bit set
1588 if (!finBit && (opcode & kControlFrameMask)) {
1589 LOG(("WebSocketChannel:: fragmented control frame code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: fragmented control frame code %d\n"
, opcode); } } while (0)
;
1590 return NS_ERROR_ILLEGAL_VALUE;
1591 }
1592
1593 if (rsvBits) {
1594 // PMCE sets RSV1 bit in the first fragment when the non-control frame
1595 // is deflated
1596 MutexAutoLock lock(mCompressorMutex);
1597 if (mPMCECompressor && rsvBits == kRsv1Bit && mFragmentAccumulator == 0 &&
1598 !(opcode & kControlFrameMask)) {
1599 mPMCECompressor->SetMessageDeflated();
1600 LOG(("WebSocketChannel::ProcessInput: received deflated frame\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: received deflated frame\n"
); } } while (0)
;
1601 } else {
1602 LOG(("WebSocketChannel::ProcessInput: unexpected reserved bits %x\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unexpected reserved bits %x\n"
, rsvBits); } } while (0)
1603 rsvBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unexpected reserved bits %x\n"
, rsvBits); } } while (0)
;
1604 return NS_ERROR_ILLEGAL_VALUE;
1605 }
1606 }
1607
1608 if (!finBit || opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) {
1609 // This is part of a fragment response
1610
1611 // Only the first frame has a non zero op code: Make sure we don't see a
1612 // first frame while some old fragments are open
1613 if ((mFragmentAccumulator != 0) &&
1614 (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION)) {
1615 LOG(("WebSocketChannel:: nested fragments\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: nested fragments\n"
); } } while (0)
;
1616 return NS_ERROR_ILLEGAL_VALUE;
1617 }
1618
1619 LOG(("WebSocketChannel:: Accumulating Fragment %" PRIu32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Accumulating Fragment %"
"u" "\n", payloadLength); } } while (0)
1620 payloadLength))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Accumulating Fragment %"
"u" "\n", payloadLength); } } while (0)
;
1621
1622 if (opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) {
1623 // Make sure this continuation fragment isn't the first fragment
1624 if (mFragmentOpcode == nsIWebSocketFrame::OPCODE_CONTINUATION) {
1625 LOG(("WebSocketHeandler:: continuation code in first fragment\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketHeandler:: continuation code in first fragment\n"
); } } while (0)
;
1626 return NS_ERROR_ILLEGAL_VALUE;
1627 }
1628
1629 // For frag > 1 move the data body back on top of the headers
1630 // so we have contiguous stream of data
1631 MOZ_ASSERT(mFramePtr + framingLength == payload,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength ==
payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1632; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1632 "payload offset from frameptr wrong")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength ==
payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1632; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1633 ::memmove(mFramePtr, payload, avail);
1634 payload = mFramePtr;
1635 if (mBuffered) mBuffered -= framingLength;
1636 } else {
1637 mFragmentOpcode = opcode;
1638 }
1639
1640 if (finBit) {
1641 LOG(("WebSocketChannel:: Finalizing Fragment\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Finalizing Fragment\n"
); } } while (0)
;
1642 payload -= mFragmentAccumulator;
1643 payloadLength += mFragmentAccumulator;
1644 avail += mFragmentAccumulator;
1645 mFragmentAccumulator = 0;
1646 opcode = mFragmentOpcode;
1647 // reset to detect if next message illegally starts with continuation
1648 mFragmentOpcode = nsIWebSocketFrame::OPCODE_CONTINUATION;
1649 } else {
1650 opcode = nsIWebSocketFrame::OPCODE_CONTINUATION;
1651 mFragmentAccumulator += payloadLength;
1652 }
1653 } else if (mFragmentAccumulator != 0 && !(opcode & kControlFrameMask)) {
1654 // This frame is not part of a fragment sequence but we
1655 // have an open fragment.. it must be a control code or else
1656 // we have a problem
1657 LOG(("WebSocketChannel:: illegal fragment sequence\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: illegal fragment sequence\n"
); } } while (0)
;
1658 return NS_ERROR_ILLEGAL_VALUE;
1659 }
1660
1661 if (mServerClosed) {
1662 LOG(("WebSocketChannel:: ignoring read frame code %d after close\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after close\n"
, opcode); } } while (0)
1663 opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after close\n"
, opcode); } } while (0)
;
1664 // nop
1665 } else if (mStopped) {
1666 LOG(("WebSocketChannel:: ignoring read frame code %d after completion\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after completion\n"
, opcode); } } while (0)
1667 opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after completion\n"
, opcode); } } while (0)
;
1668 } else if (opcode == nsIWebSocketFrame::OPCODE_TEXT) {
1669 if (mListenerMT) {
1670 nsCString utf8Data;
1671 {
1672 MutexAutoLock lock(mCompressorMutex);
1673 bool isDeflated =
1674 mPMCECompressor && mPMCECompressor->IsMessageDeflated();
1675 LOG(("WebSocketChannel:: %stext frame received\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %stext frame received\n"
, isDeflated ? "deflated " : ""); } } while (0)
1676 isDeflated ? "deflated " : ""))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %stext frame received\n"
, isDeflated ? "deflated " : ""); } } while (0)
;
1677
1678 if (isDeflated) {
1679 rv = mPMCECompressor->Inflate(payload, payloadLength, utf8Data);
1680 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1681 return rv;
1682 }
1683 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data.
Length()); } } while (0)
1684 ("WebSocketChannel:: message successfully inflated "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data.
Length()); } } while (0)
1685 "[origLength=%d, newLength=%zd]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data.
Length()); } } while (0)
1686 payloadLength, utf8Data.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data.
Length()); } } while (0)
;
1687 } else {
1688 if (!utf8Data.Assign((const char*)payload, payloadLength,
1689 mozilla::fallible)) {
1690 return NS_ERROR_OUT_OF_MEMORY;
1691 }
1692 }
1693 }
1694
1695 // Section 8.1 says to fail connection if invalid utf-8 in text message
1696 if (!IsUtf8(utf8Data)) {
1697 LOG(("WebSocketChannel:: text frame invalid utf-8\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: text frame invalid utf-8\n"
); } } while (0)
;
1698 return NS_ERROR_CANNOT_CONVERT_DATA;
1699 }
1700
1701 RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded(
1702 finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, utf8Data);
1703
1704 if (frame) {
1705 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1706 }
1707
1708 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
1709 target->Dispatch(new CallOnMessageAvailable(this, utf8Data, -1),
1710 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1711 } else {
1712 return NS_ERROR_UNEXPECTED;
1713 }
1714 if (mConnectionLogService && !mPrivateBrowsing) {
1715 mConnectionLogService->NewMsgReceived(mHost, mSerial, count);
1716 LOG(("Added new msg received for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new msg received for %s"
, mHost.get()); } } while (0)
;
1717 }
1718 }
1719 } else if (opcode & kControlFrameMask) {
1720 // control frames
1721 if (payloadLength > 125) {
1722 LOG(("WebSocketChannel:: bad control frame code %d length %d\n", opcode,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: bad control frame code %d length %d\n"
, opcode, payloadLength); } } while (0)
1723 payloadLength))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: bad control frame code %d length %d\n"
, opcode, payloadLength); } } while (0)
;
1724 return NS_ERROR_ILLEGAL_VALUE;
1725 }
1726
1727 RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded(
1728 finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, payload,
1729 payloadLength);
1730
1731 if (opcode == nsIWebSocketFrame::OPCODE_CLOSE) {
1732 LOG(("WebSocketChannel:: close received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close received\n"
); } } while (0)
;
1733 mServerClosed = true;
1734
1735 mServerCloseCode = CLOSE_NO_STATUS;
1736 if (payloadLength >= 2) {
1737 mServerCloseCode = NetworkEndian::readUint16(payload);
1738 LOG(("WebSocketChannel:: close recvd code %u\n", mServerCloseCode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close recvd code %u\n"
, mServerCloseCode); } } while (0)
;
1739 uint16_t msglen = static_cast<uint16_t>(payloadLength - 2);
1740 if (msglen > 0) {
1741 mServerCloseReason.SetLength(msglen);
1742 memcpy(mServerCloseReason.BeginWriting(), (const char*)payload + 2,
1743 msglen);
1744
1745 // section 8.1 says to replace received non utf-8 sequences
1746 // (which are non-conformant to send) with u+fffd,
1747 // but secteam feels that silently rewriting messages is
1748 // inappropriate - so we will fail the connection instead.
1749 if (!IsUtf8(mServerCloseReason)) {
1750 LOG(("WebSocketChannel:: close frame invalid utf-8\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close frame invalid utf-8\n"
); } } while (0)
;
1751 return NS_ERROR_CANNOT_CONVERT_DATA;
1752 }
1753
1754 LOG(("WebSocketChannel:: close msg %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close msg %s\n"
, mServerCloseReason.get()); } } while (0)
1755 mServerCloseReason.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close msg %s\n"
, mServerCloseReason.get()); } } while (0)
;
1756 }
1757 }
1758
1759 if (mCloseTimer) {
1760 mCloseTimer->Cancel();
1761 mCloseTimer = nullptr;
1762 }
1763
1764 if (frame) {
1765 // We send the frame immediately becuase we want to have it dispatched
1766 // before the CallOnServerClose.
1767 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1768 frame = nullptr;
1769 }
1770
1771 if (mListenerMT) {
1772 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
1773 target->Dispatch(new CallOnServerClose(this, mServerCloseCode,
1774 mServerCloseReason),
1775 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1776 } else {
1777 return NS_ERROR_UNEXPECTED;
1778 }
1779 }
1780
1781 if (mClientClosed) ReleaseSession();
1782 } else if (opcode == nsIWebSocketFrame::OPCODE_PING) {
1783 LOG(("WebSocketChannel:: ping received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ping received\n"
); } } while (0)
;
1784 GeneratePong(payload, payloadLength);
1785 } else if (opcode == nsIWebSocketFrame::OPCODE_PONG) {
1786 // opcode OPCODE_PONG: the mere act of receiving the packet is all we
1787 // need to do for the pong to trigger the activity timers
1788 LOG(("WebSocketChannel:: pong received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: pong received\n"
); } } while (0)
;
1789 } else {
1790 /* unknown control frame opcode */
1791 LOG(("WebSocketChannel:: unknown control op code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: unknown control op code %d\n"
, opcode); } } while (0)
;
1792 return NS_ERROR_ILLEGAL_VALUE;
1793 }
1794
1795 if (mFragmentAccumulator) {
1796 // Remove the control frame from the stream so we have a contiguous
1797 // data buffer of reassembled fragments
1798 LOG(("WebSocketChannel:: Removing Control From Read buffer\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Removing Control From Read buffer\n"
); } } while (0)
;
1799 MOZ_ASSERT(mFramePtr + framingLength == payload,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength ==
payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1800; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1800 "payload offset from frameptr wrong")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength ==
payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1800; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1801 ::memmove(mFramePtr, payload + payloadLength, avail - payloadLength);
1802 payload = mFramePtr;
1803 avail -= payloadLength;
1804 if (mBuffered) mBuffered -= framingLength + payloadLength;
1805 payloadLength = 0;
1806 }
1807
1808 if (frame) {
1809 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1810 }
1811 } else if (opcode == nsIWebSocketFrame::OPCODE_BINARY) {
1812 if (mListenerMT) {
1813 nsCString binaryData;
1814 {
1815 MutexAutoLock lock(mCompressorMutex);
1816 bool isDeflated =
1817 mPMCECompressor && mPMCECompressor->IsMessageDeflated();
1818 LOG(("WebSocketChannel:: %sbinary frame received\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %sbinary frame received\n"
, isDeflated ? "deflated " : ""); } } while (0)
1819 isDeflated ? "deflated " : ""))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %sbinary frame received\n"
, isDeflated ? "deflated " : ""); } } while (0)
;
1820
1821 if (isDeflated) {
1822 rv = mPMCECompressor->Inflate(payload, payloadLength, binaryData);
1823 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1824 return rv;
1825 }
1826 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, binaryData
.Length()); } } while (0)
1827 ("WebSocketChannel:: message successfully inflated "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, binaryData
.Length()); } } while (0)
1828 "[origLength=%d, newLength=%zd]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, binaryData
.Length()); } } while (0)
1829 payloadLength, binaryData.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated "
"[origLength=%d, newLength=%zd]\n", payloadLength, binaryData
.Length()); } } while (0)
;
1830 } else {
1831 if (!binaryData.Assign((const char*)payload, payloadLength,
1832 mozilla::fallible)) {
1833 return NS_ERROR_OUT_OF_MEMORY;
1834 }
1835 }
1836 }
1837
1838 RefPtr<WebSocketFrame> frame =
1839 mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3,
1840 opcode, maskBit, mask, binaryData);
1841 if (frame) {
1842 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1843 }
1844
1845 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
1846 target->Dispatch(
1847 new CallOnMessageAvailable(this, binaryData, binaryData.Length()),
1848 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1849 } else {
1850 return NS_ERROR_UNEXPECTED;
1851 }
1852 // To add the header to 'Networking Dashboard' log
1853 if (mConnectionLogService && !mPrivateBrowsing) {
1854 mConnectionLogService->NewMsgReceived(mHost, mSerial, count);
1855 LOG(("Added new received msg for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new received msg for %s"
, mHost.get()); } } while (0)
;
1856 }
1857 }
1858 } else if (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION) {
1859 /* unknown opcode */
1860 LOG(("WebSocketChannel:: unknown op code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: unknown op code %d\n"
, opcode); } } while (0)
;
1861 return NS_ERROR_ILLEGAL_VALUE;
1862 }
1863
1864 mFramePtr = payload + payloadLength;
1865 avail -= payloadLength;
1866 totalAvail = avail;
1867 }
1868
1869 // Adjust the stateful buffer. If we were operating off the stack and
1870 // now have a partial message then transition to the buffer, or if
1871 // we were working off the buffer but no longer have any active state
1872 // then transition to the stack
1873 if (!IsPersistentFramePtr()) {
1874 mBuffered = 0;
1875
1876 if (mFragmentAccumulator) {
1877 LOG(("WebSocketChannel:: Setup Buffer due to fragment"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Setup Buffer due to fragment"
); } } while (0)
;
1878
1879 if (!UpdateReadBuffer(mFramePtr - mFragmentAccumulator,
1880 totalAvail + mFragmentAccumulator, 0, nullptr)) {
1881 return NS_ERROR_FILE_TOO_BIG;
1882 }
1883
1884 // UpdateReadBuffer will reset the frameptr to the beginning
1885 // of new saved state, so we need to skip past processed framgents
1886 mFramePtr += mFragmentAccumulator;
1887 } else if (totalAvail) {
1888 LOG(("WebSocketChannel:: Setup Buffer due to partial frame"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Setup Buffer due to partial frame"
); } } while (0)
;
1889 if (!UpdateReadBuffer(mFramePtr, totalAvail, 0, nullptr)) {
1890 return NS_ERROR_FILE_TOO_BIG;
1891 }
1892 }
1893 } else if (!mFragmentAccumulator && !totalAvail) {
1894 // If we were working off a saved buffer state and there is no partial
1895 // frame or fragment in process, then revert to stack behavior
1896 LOG(("WebSocketChannel:: Internal buffering not needed anymore"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Internal buffering not needed anymore"
); } } while (0)
;
1897 mBuffered = 0;
1898
1899 // release memory if we've been processing a large message
1900 if (mBufferSize > kIncomingBufferStableSize) {
1901 mBufferSize = kIncomingBufferStableSize;
1902 free(mBuffer);
1903 mBuffer = (uint8_t*)moz_xmalloc(mBufferSize);
1904 }
1905 }
1906 return NS_OK;
1907}
1908
1909/* static */
1910void WebSocketChannel::ApplyMask(uint32_t mask, uint8_t* data, uint64_t len) {
1911 if (!data || len == 0) return;
1912
1913 // Optimally we want to apply the mask 32 bits at a time,
1914 // but the buffer might not be alligned. So we first deal with
1915 // 0 to 3 bytes of preamble individually
1916
1917 while (len && (reinterpret_cast<uintptr_t>(data) & 3)) {
1918 *data ^= mask >> 24;
1919 mask = RotateLeft(mask, 8);
1920 data++;
1921 len--;
1922 }
1923
1924 // perform mask on full words of data
1925
1926 uint32_t* iData = (uint32_t*)data;
1927 uint32_t* end = iData + (len / 4);
1928 NetworkEndian::writeUint32(&mask, mask);
1929 for (; iData < end; iData++) *iData ^= mask;
1930 mask = NetworkEndian::readUint32(&mask);
1931 data = (uint8_t*)iData;
1932 len = len % 4;
1933
1934 // There maybe up to 3 trailing bytes that need to be dealt with
1935 // individually
1936
1937 while (len) {
1938 *data ^= mask >> 24;
1939 mask = RotateLeft(mask, 8);
1940 data++;
1941 len--;
1942 }
1943}
1944
1945void WebSocketChannel::GeneratePing() {
1946 nsAutoCString buf;
1947 buf.AssignLiteral("PING");
1948 EnqueueOutgoingMessage(mOutgoingPingMessages,
1949 new OutboundMessage(kMsgTypePing, buf));
1950}
1951
1952void WebSocketChannel::GeneratePong(uint8_t* payload, uint32_t len) {
1953 nsAutoCString buf;
1954 buf.SetLength(len);
1955 if (buf.Length() < len) {
1956 LOG(("WebSocketChannel::GeneratePong Allocation Failure\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GeneratePong Allocation Failure\n"
); } } while (0)
;
1957 return;
1958 }
1959
1960 memcpy(buf.BeginWriting(), payload, len);
1961 EnqueueOutgoingMessage(mOutgoingPongMessages,
1962 new OutboundMessage(kMsgTypePong, buf));
1963}
1964
1965void WebSocketChannel::EnqueueOutgoingMessage(nsDeque<OutboundMessage>& aQueue,
1966 OutboundMessage* aMsg) {
1967 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 1967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 1967; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1968
1969 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p "
"queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg
->GetMsgType()], aMsg->Length()); } } while (0)
1970 ("WebSocketChannel::EnqueueOutgoingMessage %p "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p "
"queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg
->GetMsgType()], aMsg->Length()); } } while (0)
1971 "queueing msg %p [type=%s len=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p "
"queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg
->GetMsgType()], aMsg->Length()); } } while (0)
1972 this, aMsg, msgNames[aMsg->GetMsgType()], aMsg->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p "
"queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg
->GetMsgType()], aMsg->Length()); } } while (0)
;
1973
1974 aQueue.Push(aMsg);
1975 if (mSocketOut) {
1976 OnOutputStreamReady(mSocketOut);
1977 } else {
1978 DoEnqueueOutgoingMessage();
1979 }
1980}
1981
1982uint16_t WebSocketChannel::ResultToCloseCode(nsresult resultCode) {
1983 if (NS_SUCCEEDED(resultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(resultCode)), 1))
)
) return CLOSE_NORMAL;
1984
1985 switch (resultCode) {
1986 case NS_ERROR_FILE_TOO_BIG:
1987 case NS_ERROR_OUT_OF_MEMORY:
1988 return CLOSE_TOO_LARGE;
1989 case NS_ERROR_CANNOT_CONVERT_DATA:
1990 return CLOSE_INVALID_PAYLOAD;
1991 case NS_ERROR_UNEXPECTED:
1992 return CLOSE_INTERNAL_ERROR;
1993 default:
1994 return CLOSE_PROTOCOL_ERROR;
1995 }
1996}
1997
1998void WebSocketChannel::PrimeNewOutgoingMessage() {
1999 LOG(("WebSocketChannel::PrimeNewOutgoingMessage() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage() %p\n"
, this); } } while (0)
;
2000 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2000); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 2000; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2001 MOZ_ASSERT(!mCurrentOut, "Current message in progress")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCurrentOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCurrentOut))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mCurrentOut" " ("
"Current message in progress" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCurrentOut"
") (" "Current message in progress" ")"); do { *((volatile int
*)__null) = 2001; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2002
2003 nsresult rv = NS_OK;
2004
2005 mCurrentOut = mOutgoingPongMessages.PopFront();
2006 if (mCurrentOut) {
2007 MOZ_ASSERT(mCurrentOut->GetMsgType() == kMsgTypePong, "Not pong message!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCurrentOut->GetMsgType() == kMsgTypePong)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mCurrentOut->GetMsgType() == kMsgTypePong))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePong"
" (" "Not pong message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePong"
") (" "Not pong message!" ")"); do { *((volatile int*)__null
) = 2007; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2008 } else {
2009 mCurrentOut = mOutgoingPingMessages.PopFront();
2010 if (mCurrentOut) {
2011 MOZ_ASSERT(mCurrentOut->GetMsgType() == kMsgTypePing,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCurrentOut->GetMsgType() == kMsgTypePing)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mCurrentOut->GetMsgType() == kMsgTypePing))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePing"
" (" "Not ping message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing"
") (" "Not ping message!" ")"); do { *((volatile int*)__null
) = 2012; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2012 "Not ping message!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCurrentOut->GetMsgType() == kMsgTypePing)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mCurrentOut->GetMsgType() == kMsgTypePing))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePing"
" (" "Not ping message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing"
") (" "Not ping message!" ")"); do { *((volatile int*)__null
) = 2012; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2013 } else {
2014 mCurrentOut = mOutgoingMessages.PopFront();
2015 }
2016 }
2017
2018 if (!mCurrentOut) return;
2019
2020 auto cleanupAfterFailure =
2021 MakeScopeExit([&] { DeleteCurrentOutGoingMessage(); });
2022
2023 WsMsgType msgType = mCurrentOut->GetMsgType();
2024
2025 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage "
"%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut
, msgNames[msgType], mCurrentOut->Length()); } } while (0)
2026 ("WebSocketChannel::PrimeNewOutgoingMessage "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage "
"%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut
, msgNames[msgType], mCurrentOut->Length()); } } while (0)
2027 "%p found queued msg %p [type=%s len=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage "
"%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut
, msgNames[msgType], mCurrentOut->Length()); } } while (0)
2028 this, mCurrentOut, msgNames[msgType], mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage "
"%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut
, msgNames[msgType], mCurrentOut->Length()); } } while (0)
;
2029
2030 mCurrentOutSent = 0;
2031 mHdrOut = mOutHeader;
2032
2033 uint8_t maskBit = mIsServerSide ? 0 : kMaskBit;
2034 uint8_t maskSize = mIsServerSide ? 0 : 4;
2035
2036 uint8_t* payload = nullptr;
2037
2038 if (msgType == kMsgTypeFin) {
2039 // This is a demand to create a close message
2040 if (mClientClosed) {
2041 DeleteCurrentOutGoingMessage();
2042 PrimeNewOutgoingMessage();
2043 cleanupAfterFailure.release();
2044 return;
2045 }
2046
2047 mClientClosed = true;
2048 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_CLOSE;
2049 mOutHeader[1] = maskBit;
2050
2051 // payload is offset 2 plus size of the mask
2052 payload = mOutHeader + 2 + maskSize;
2053
2054 // The close reason code sits in the first 2 bytes of payload
2055 // If the channel user provided a code and reason during Close()
2056 // and there isn't an internal error, use that.
2057 if (NS_SUCCEEDED(mStopOnClose)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStopOnClose)), 1
)))
) {
2058 MutexAutoLock lock(mMutex);
2059 if (mScriptCloseCode) {
2060 NetworkEndian::writeUint16(payload, mScriptCloseCode);
2061 mOutHeader[1] += 2;
2062 mHdrOutToSend = 4 + maskSize;
2063 if (!mScriptCloseReason.IsEmpty()) {
2064 MOZ_ASSERT(mScriptCloseReason.Length() <= 123,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptCloseReason.Length() <= 123)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(mScriptCloseReason.Length() <= 123))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mScriptCloseReason.Length() <= 123"
" (" "Close Reason Too Long" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123"
") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null
) = 2065; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2065 "Close Reason Too Long")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptCloseReason.Length() <= 123)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(mScriptCloseReason.Length() <= 123))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mScriptCloseReason.Length() <= 123"
" (" "Close Reason Too Long" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123"
") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null
) = 2065; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2066 mOutHeader[1] += mScriptCloseReason.Length();
2067 mHdrOutToSend += mScriptCloseReason.Length();
2068 memcpy(payload + 2, mScriptCloseReason.BeginReading(),
2069 mScriptCloseReason.Length());
2070 }
2071 } else {
2072 // No close code/reason, so payload length = 0. We must still send mask
2073 // even though it's not used. Keep payload offset so we write mask
2074 // below.
2075 mHdrOutToSend = 2 + maskSize;
2076 }
2077 } else {
2078 NetworkEndian::writeUint16(payload, ResultToCloseCode(mStopOnClose));
2079 mOutHeader[1] += 2;
2080 mHdrOutToSend = 4 + maskSize;
2081 }
2082
2083 if (mServerClosed) {
2084 /* bidi close complete */
2085 mReleaseOnTransmit = 1;
2086 } else if (NS_FAILED(mStopOnClose)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStopOnClose)), 0)
))
) {
2087 /* result of abort session - give up */
2088 StopSession(mStopOnClose);
2089 } else {
2090 /* wait for reciprocal close from server */
2091 rv = NS_NewTimerWithCallback(getter_AddRefs(mCloseTimer), this,
2092 mCloseTimeout, nsITimer::TYPE_ONE_SHOT);
2093 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2094 StopSession(rv);
2095 }
2096 }
2097 } else {
2098 switch (msgType) {
2099 case kMsgTypePong:
2100 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PONG;
2101 break;
2102 case kMsgTypePing:
2103 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PING;
2104 break;
2105 case kMsgTypeString:
2106 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_TEXT;
2107 break;
2108 case kMsgTypeStream:
2109 // HACK ALERT: read in entire stream into string.
2110 // Will block socket transport thread if file is blocking.
2111 // TODO: bug 704447: don't block socket thread!
2112 rv = mCurrentOut->ConvertStreamToString();
2113 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2114 AbortSession(NS_ERROR_FILE_TOO_BIG);
2115 return;
2116 }
2117 // Now we're a binary string
2118 msgType = kMsgTypeBinaryString;
2119
2120 // no break: fall down into binary string case
2121 [[fallthrough]];
2122
2123 case kMsgTypeBinaryString:
2124 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_BINARY;
2125 break;
2126 case kMsgTypeFin:
2127 MOZ_ASSERT(false, "unreachable")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "unreachable"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"unreachable" ")"); do { *((volatile int*)__null) = 2127; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
; // avoid compiler warning
2128 break;
2129 }
2130
2131 // deflate the payload if PMCE is negotiated
2132 MutexAutoLock lock(mCompressorMutex);
2133 if (mPMCECompressor &&
2134 (msgType == kMsgTypeString || msgType == kMsgTypeBinaryString)) {
2135 if (mCurrentOut->DeflatePayload(mPMCECompressor.get())) {
2136 // The payload was deflated successfully, set RSV1 bit
2137 mOutHeader[0] |= kRsv1Bit;
2138
2139 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "
"deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut
, mCurrentOut->OrigLength(), mCurrentOut->Length()); } }
while (0)
2140 ("WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "
"deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut
, mCurrentOut->OrigLength(), mCurrentOut->Length()); } }
while (0)
2141 "deflated [origLength=%d, newLength=%d].\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "
"deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut
, mCurrentOut->OrigLength(), mCurrentOut->Length()); } }
while (0)
2142 this, mCurrentOut, mCurrentOut->OrigLength(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "
"deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut
, mCurrentOut->OrigLength(), mCurrentOut->Length()); } }
while (0)
2143 mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "
"deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut
, mCurrentOut->OrigLength(), mCurrentOut->Length()); } }
while (0)
;
2144 }
2145 }
2146
2147 if (mCurrentOut->Length() < 126) {
2148 mOutHeader[1] = mCurrentOut->Length() | maskBit;
2149 mHdrOutToSend = 2 + maskSize;
2150 } else if (mCurrentOut->Length() <= 0xffff) {
2151 mOutHeader[1] = 126 | maskBit;
2152 NetworkEndian::writeUint16(mOutHeader + sizeof(uint16_t),
2153 mCurrentOut->Length());
2154 mHdrOutToSend = 4 + maskSize;
2155 } else {
2156 mOutHeader[1] = 127 | maskBit;
2157 NetworkEndian::writeUint64(mOutHeader + 2, mCurrentOut->Length());
2158 mHdrOutToSend = 10 + maskSize;
2159 }
2160 payload = mOutHeader + mHdrOutToSend;
2161 }
2162
2163 MOZ_ASSERT(payload, "payload offset not found")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(payload)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(payload))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("payload" " (" "payload offset not found"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "payload" ") ("
"payload offset not found" ")"); do { *((volatile int*)__null
) = 2163; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2164
2165 uint32_t mask = 0;
2166 if (!mIsServerSide) {
2167 // Perform the sending mask. Never use a zero mask
2168 do {
2169 static_assert(4 == sizeof(mask), "Size of the mask should be equal to 4");
2170 nsresult rv = mRandomGenerator->GenerateRandomBytesInto(mask);
2171 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2172 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): "
"GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t
>(rv)); } } while (0)
2173 ("WebSocketChannel::PrimeNewOutgoingMessage(): "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): "
"GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t
>(rv)); } } while (0)
2174 "GenerateRandomBytes failure %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): "
"GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t
>(rv)); } } while (0)
2175 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): "
"GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t
>(rv)); } } while (0)
;
2176 AbortSession(rv);
2177 return;
2178 }
2179 } while (!mask);
2180 NetworkEndian::writeUint32(payload - sizeof(uint32_t), mask);
2181 }
2182
2183 LOG(("WebSocketChannel::PrimeNewOutgoingMessage() using mask %08x\n", mask))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage() using mask %08x\n"
, mask); } } while (0)
;
2184
2185 // We don't mask the framing, but occasionally we stick a little payload
2186 // data in the buffer used for the framing. Close frames are the current
2187 // example. This data needs to be masked, but it is never more than a
2188 // handful of bytes and might rotate the mask, so we can just do it locally.
2189 // For real data frames we ship the bulk of the payload off to ApplyMask()
2190
2191 RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded(
2192 mOutHeader[0] & WebSocketChannel::kFinalFragBit,
2193 mOutHeader[0] & WebSocketChannel::kRsv1Bit,
2194 mOutHeader[0] & WebSocketChannel::kRsv2Bit,
2195 mOutHeader[0] & WebSocketChannel::kRsv3Bit,
2196 mOutHeader[0] & WebSocketChannel::kOpcodeBitsMask,
2197 mOutHeader[1] & WebSocketChannel::kMaskBit, mask, payload,
2198 mHdrOutToSend - (payload - mOutHeader), mCurrentOut->BeginOrigReading(),
2199 mCurrentOut->OrigLength());
2200
2201 if (frame) {
2202 mService->FrameSent(mSerial, mInnerWindowID, frame.forget());
2203 }
2204
2205 if (mask) {
2206 while (payload < (mOutHeader + mHdrOutToSend)) {
2207 *payload ^= mask >> 24;
2208 mask = RotateLeft(mask, 8);
2209 payload++;
2210 }
2211
2212 // Mask the real message payloads
2213 ApplyMask(mask, mCurrentOut->BeginWriting(), mCurrentOut->Length());
2214 }
2215
2216 int32_t len = mCurrentOut->Length();
2217
2218 // for small frames, copy it all together for a contiguous write
2219 if (len && len <= kCopyBreak) {
2220 memcpy(mOutHeader + mHdrOutToSend, mCurrentOut->BeginWriting(), len);
2221 mHdrOutToSend += len;
2222 mCurrentOutSent = len;
2223 }
2224
2225 // Transmitting begins - mHdrOutToSend bytes from mOutHeader and
2226 // mCurrentOut->Length() bytes from mCurrentOut. The latter may be
2227 // coaleseced into the former for small messages or as the result of the
2228 // compression process.
2229
2230 cleanupAfterFailure.release();
2231}
2232
2233void WebSocketChannel::DeleteCurrentOutGoingMessage() {
2234 delete mCurrentOut;
2235 mCurrentOut = nullptr;
2236 mCurrentOutSent = 0;
2237}
2238
2239void WebSocketChannel::EnsureHdrOut(uint32_t size) {
2240 LOG(("WebSocketChannel::EnsureHdrOut() %p [%d]\n", this, size))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnsureHdrOut() %p [%d]\n"
, this, size); } } while (0)
;
2241
2242 if (mDynamicOutputSize < size) {
2243 mDynamicOutputSize = size;
2244 mDynamicOutput = (uint8_t*)moz_xrealloc(mDynamicOutput, mDynamicOutputSize);
2245 }
2246
2247 mHdrOut = mDynamicOutput;
2248}
2249
2250namespace {
2251
2252class RemoveObserverRunnable : public Runnable {
2253 RefPtr<WebSocketChannel> mChannel;
2254
2255 public:
2256 explicit RemoveObserverRunnable(WebSocketChannel* aChannel)
2257 : Runnable("net::RemoveObserverRunnable"), mChannel(aChannel) {}
2258
2259 NS_IMETHODvirtual nsresult Run() override {
2260 nsCOMPtr<nsIObserverService> observerService =
2261 mozilla::services::GetObserverService();
2262 if (!observerService) {
2263 NS_WARNING("failed to get observer service")NS_DebugBreak(NS_DEBUG_WARNING, "failed to get observer service"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2263)
;
2264 return NS_OK;
2265 }
2266
2267 observerService->RemoveObserver(mChannel, NS_NETWORK_LINK_TOPIC"network:link-status-changed");
2268 return NS_OK;
2269 }
2270};
2271
2272} // namespace
2273
2274void WebSocketChannel::CleanupConnection() {
2275 // normally this should be called on socket thread, but it may be called
2276 // on MainThread
2277
2278 LOG(("WebSocketChannel::CleanupConnection() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CleanupConnection() %p"
, this); } } while (0)
;
2279 // This needs to run on the IOThread so we don't need to lock a bunch of these
2280 if (!mIOThread->IsOnCurrentThread()) {
2281 mIOThread->Dispatch(
2282 NewRunnableMethod("net::WebSocketChannel::CleanupConnection", this,
2283 &WebSocketChannel::CleanupConnection),
2284 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2285 return;
2286 }
2287
2288 if (mLingeringCloseTimer) {
2289 mLingeringCloseTimer->Cancel();
2290 mLingeringCloseTimer = nullptr;
2291 }
2292
2293 if (mSocketIn) {
2294 if (mDataStarted) {
2295 mSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
2296 }
2297 mSocketIn = nullptr;
2298 }
2299
2300 if (mSocketOut) {
2301 mSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
2302 mSocketOut = nullptr;
2303 }
2304
2305 if (mTransport) {
2306 mTransport->SetSecurityCallbacks(nullptr);
2307 mTransport->SetEventSink(nullptr, nullptr);
2308 mTransport->Close(NS_BASE_STREAM_CLOSED);
2309 mTransport = nullptr;
2310 }
2311
2312 if (mConnection) {
2313 mConnection->Close();
2314 mConnection = nullptr;
2315 }
2316
2317 if (mConnectionLogService && !mPrivateBrowsing) {
2318 mConnectionLogService->RemoveHost(mHost, mSerial);
2319 }
2320
2321 // The observer has to be removed on the main-thread.
2322 NS_DispatchToMainThread(new RemoveObserverRunnable(this));
2323
2324 DecrementSessionCount();
2325}
2326
2327void WebSocketChannel::StopSession(nsresult reason) {
2328 LOG(("WebSocketChannel::StopSession() %p [%" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StopSession() %p [%"
"x" "]\n", this, static_cast<uint32_t>(reason)); } } while
(0)
2329 static_cast<uint32_t>(reason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StopSession() %p [%"
"x" "]\n", this, static_cast<uint32_t>(reason)); } } while
(0)
;
2330
2331 {
2332 MutexAutoLock lock(mMutex);
2333 if (mStopped) {
2334 return;
2335 }
2336 mStopped = true;
2337 }
2338
2339 DoStopSession(reason);
2340}
2341
2342void WebSocketChannel::DoStopSession(nsresult reason) {
2343 LOG(("WebSocketChannel::DoStopSession() %p [%" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession() %p [%"
"x" "]\n", this, static_cast<uint32_t>(reason)); } } while
(0)
2344 static_cast<uint32_t>(reason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession() %p [%"
"x" "]\n", this, static_cast<uint32_t>(reason)); } } while
(0)
;
2345
2346 // normally this should be called on socket thread, but it is ok to call it
2347 // from OnStartRequest before the socket thread machine has gotten underway.
2348 // If mDataStarted is false, this is called on MainThread for Close().
2349 // Otherwise it should be called on the IO thread
2350
2351 MOZ_ASSERT(mStopped)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mStopped", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2351); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")"
); do { *((volatile int*)__null) = 2351; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2352 MOZ_ASSERT(mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread() || mTCPClosed || !
mDataStarted)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread()
|| mTCPClosed || !mDataStarted))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted"
")"); do { *((volatile int*)__null) = 2352; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2353
2354 if (!mOpenedHttpChannel) {
2355 // The HTTP channel information will never be used in this case
2356 NS_ReleaseOnMainThread("WebSocketChannel::mChannel", mChannel.forget());
2357 NS_ReleaseOnMainThread("WebSocketChannel::mHttpChannel",
2358 mHttpChannel.forget());
2359 NS_ReleaseOnMainThread("WebSocketChannel::mLoadGroup", mLoadGroup.forget());
2360 NS_ReleaseOnMainThread("WebSocketChannel::mCallbacks", mCallbacks.forget());
2361 }
2362
2363 if (mCloseTimer) {
2364 mCloseTimer->Cancel();
2365 mCloseTimer = nullptr;
2366 }
2367
2368 // mOpenTimer must be null if mDataStarted is true and we're not on MainThread
2369 if (mOpenTimer) {
2370 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
2370; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2371 mOpenTimer->Cancel();
2372 mOpenTimer = nullptr;
2373 }
2374
2375 {
2376 MutexAutoLock lock(mMutex);
2377 if (mReconnectDelayTimer) {
2378 mReconnectDelayTimer->Cancel();
2379 NS_ReleaseOnMainThread("WebSocketChannel::mMutex",
2380 mReconnectDelayTimer.forget());
2381 }
2382 }
2383
2384 if (mPingTimer) {
2385 mPingTimer->Cancel();
2386 mPingTimer = nullptr;
2387 }
2388
2389 if (!mTCPClosed && mDataStarted) {
2390 if (mSocketIn) {
2391 // Drain, within reason, this socket. if we leave any data
2392 // unconsumed (including the tcp fin) a RST will be generated
2393 // The right thing to do here is shutdown(SHUT_WR) and then wait
2394 // a little while to see if any data comes in.. but there is no
2395 // reason to delay things for that when the websocket handshake
2396 // is supposed to guarantee a quiet connection except for that fin.
2397
2398 char buffer[512];
2399 uint32_t count = 0;
2400 uint32_t total = 0;
2401 nsresult rv;
2402 do {
2403 total += count;
2404 rv = mSocketIn->Read(buffer, 512, &count);
2405 if (rv != NS_BASE_STREAM_WOULD_BLOCK && (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || count == 0)) {
2406 mTCPClosed = true;
2407 }
2408 } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && count > 0 && total < 32000);
2409 } else if (mConnection) {
2410 mConnection->DrainSocketData();
2411 }
2412 }
2413
2414 int32_t sessionCount = kLingeringCloseThreshold;
2415 nsWSAdmissionManager::GetSessionCount(sessionCount);
2416
2417 if (!mTCPClosed && (mTransport || mConnection) &&
2418 sessionCount < kLingeringCloseThreshold) {
2419 // 7.1.1 says that the client SHOULD wait for the server to close the TCP
2420 // connection. This is so we can reuse port numbers before 2 MSL expires,
2421 // which is not really as much of a concern for us as the amount of state
2422 // that might be accrued by keeping this channel object around waiting for
2423 // the server. We handle the SHOULD by waiting a short time in the common
2424 // case, but not waiting in the case of high concurrency.
2425 //
2426 // Normally this will be taken care of in AbortSession() after mTCPClosed
2427 // is set when the server close arrives without waiting for the timeout to
2428 // expire.
2429
2430 LOG(("WebSocketChannel::DoStopSession: Wait for Server TCP close"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession: Wait for Server TCP close"
); } } while (0)
;
2431
2432 nsresult rv;
2433 rv = NS_NewTimerWithCallback(getter_AddRefs(mLingeringCloseTimer), this,
2434 kLingeringCloseTimeout,
2435 nsITimer::TYPE_ONE_SHOT);
2436 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CleanupConnection();
2437 } else {
2438 CleanupConnection();
2439 }
2440
2441 {
2442 MutexAutoLock lock(mMutex);
2443 if (mCancelable) {
2444 mCancelable->Cancel(NS_ERROR_UNEXPECTED);
2445 mCancelable = nullptr;
2446 }
2447 }
2448
2449 {
2450 MutexAutoLock lock(mCompressorMutex);
2451 mPMCECompressor = nullptr;
2452 }
2453 if (!mCalledOnStop) {
2454 mCalledOnStop = true;
2455
2456 nsWSAdmissionManager::OnStopSession(this, reason);
2457
2458 RefPtr<CallOnStop> runnable = new CallOnStop(this, reason);
2459 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
2460 target->Dispatch(runnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2461 }
2462 }
2463}
2464
2465// Called from MainThread, and called from IOThread in
2466// PrimeNewOutgoingMessage
2467void WebSocketChannel::AbortSession(nsresult reason) {
2468 LOG(("WebSocketChannel::AbortSession() %p [reason %" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %"
"x" "] stopped = %d\n", this, static_cast<uint32_t>(reason
), !!mStopped); } } while (0)
2469 "] stopped = %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %"
"x" "] stopped = %d\n", this, static_cast<uint32_t>(reason
), !!mStopped); } } while (0)
2470 this, static_cast<uint32_t>(reason), !!mStopped))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %"
"x" "] stopped = %d\n", this, static_cast<uint32_t>(reason
), !!mStopped); } } while (0)
;
2471
2472 MOZ_ASSERT(NS_FAILED(reason), "reason must be a failure!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)),
0))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)),
0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))" " ("
"reason must be a failure!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))"
") (" "reason must be a failure!" ")"); do { *((volatile int
*)__null) = 2472; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2473
2474 // normally this should be called on socket thread, but it is ok to call it
2475 // from the main thread before StartWebsocketData() has completed
2476 MOZ_ASSERT(mIOThread->IsOnCurrentThread() || !mDataStarted)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread() || !mDataStarted)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mIOThread->IsOnCurrentThread() || !mDataStarted))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mIOThread->IsOnCurrentThread() || !mDataStarted"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || !mDataStarted"
")"); do { *((volatile int*)__null) = 2476; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2477
2478 // When we are failing we need to close the TCP connection immediately
2479 // as per 7.1.1
2480 mTCPClosed = true;
2481
2482 if (mLingeringCloseTimer) {
2483 MOZ_ASSERT(mStopped, "Lingering without Stop")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mStopped" " (" "Lingering without Stop"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") ("
"Lingering without Stop" ")"); do { *((volatile int*)__null)
= 2483; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2484 LOG(("WebSocketChannel:: Cleanup connection based on TCP Close"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Cleanup connection based on TCP Close"
); } } while (0)
;
2485 CleanupConnection();
2486 return;
2487 }
2488
2489 {
2490 MutexAutoLock lock(mMutex);
2491 if (mStopped) {
2492 return;
2493 }
2494
2495 if ((mTransport || mConnection) && reason != NS_BASE_STREAM_CLOSED &&
2496 !mRequestedClose && !mClientClosed && !mServerClosed && mDataStarted) {
2497 mRequestedClose = true;
2498 mStopOnClose = reason;
2499 mIOThread->Dispatch(
2500 new OutboundEnqueuer(this,
2501 new OutboundMessage(kMsgTypeFin, VoidCString())),
2502 nsIEventTarget::DISPATCH_NORMAL);
2503 return;
2504 }
2505
2506 mStopped = true;
2507 }
2508
2509 DoStopSession(reason);
2510}
2511
2512// ReleaseSession is called on orderly shutdown
2513void WebSocketChannel::ReleaseSession() {
2514 LOG(("WebSocketChannel::ReleaseSession() %p stopped = %d\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReleaseSession() %p stopped = %d\n"
, this, !!mStopped); } } while (0)
2515 !!mStopped))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReleaseSession() %p stopped = %d\n"
, this, !!mStopped); } } while (0)
;
2516 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 2516; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2517
2518 StopSession(NS_OK);
2519}
2520
2521void WebSocketChannel::IncrementSessionCount() {
2522 if (!mIncrementedSessionCount) {
2523 nsWSAdmissionManager::IncrementSessionCount();
2524 mIncrementedSessionCount = true;
2525 }
2526}
2527
2528void WebSocketChannel::DecrementSessionCount() {
2529 // Make sure we decrement session count only once, and only if we incremented
2530 // it. This code is thread-safe: sWebSocketAdmissions->DecrementSessionCount
2531 // is atomic, and mIncrementedSessionCount/mDecrementedSessionCount are set at
2532 // times when they'll never be a race condition for checking/setting them.
2533 if (mIncrementedSessionCount && !mDecrementedSessionCount) {
2534 nsWSAdmissionManager::DecrementSessionCount();
2535 mDecrementedSessionCount = true;
2536 }
2537}
2538
2539namespace {
2540enum ExtensionParseMode { eParseServerSide, eParseClientSide };
2541}
2542
2543static nsresult ParseWebSocketExtension(const nsACString& aExtension,
2544 ExtensionParseMode aMode,
2545 bool& aClientNoContextTakeover,
2546 bool& aServerNoContextTakeover,
2547 int32_t& aClientMaxWindowBits,
2548 int32_t& aServerMaxWindowBits) {
2549 nsCCharSeparatedTokenizer tokens(aExtension, ';');
2550
2551 if (!tokens.hasMoreTokens() ||
2552 !tokens.nextToken().EqualsLiteral("permessage-deflate")) {
2553 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: "
"HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n"
, TPromiseFlatString<char>(aExtension).get()); } } while
(0)
2554 ("WebSocketChannel::ParseWebSocketExtension: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: "
"HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n"
, TPromiseFlatString<char>(aExtension).get()); } } while
(0)
2555 "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: "
"HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n"
, TPromiseFlatString<char>(aExtension).get()); } } while
(0)
2556 PromiseFlatCString(aExtension).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: "
"HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n"
, TPromiseFlatString<char>(aExtension).get()); } } while
(0)
;
2557 return NS_ERROR_ILLEGAL_VALUE;
2558 }
2559
2560 aClientNoContextTakeover = aServerNoContextTakeover = false;
2561 aClientMaxWindowBits = aServerMaxWindowBits = -1;
2562
2563 while (tokens.hasMoreTokens()) {
2564 auto token = tokens.nextToken();
2565
2566 int32_t nameEnd, valueStart;
2567 int32_t delimPos = token.FindChar('=');
2568 if (delimPos == kNotFound) {
2569 nameEnd = token.Length();
2570 valueStart = token.Length();
2571 } else {
2572 nameEnd = delimPos;
2573 valueStart = delimPos + 1;
2574 }
2575
2576 auto paramName = Substring(token, 0, nameEnd);
2577 auto paramValue = Substring(token, valueStart);
2578
2579 if (paramName.EqualsLiteral("client_no_context_takeover")) {
2580 if (!paramValue.IsEmpty()) {
2581 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"client_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
2582 ("WebSocketChannel::ParseWebSocketExtension: parameter "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"client_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
2583 "client_no_context_takeover must not have value, found %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"client_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
2584 PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"client_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
;
2585 return NS_ERROR_ILLEGAL_VALUE;
2586 }
2587 if (aClientNoContextTakeover) {
2588 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters client_no_context_takeover\n"); } } while (0)
2589 ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters client_no_context_takeover\n"); } } while (0)
2590 "parameters client_no_context_takeover\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters client_no_context_takeover\n"); } } while (0)
;
2591 return NS_ERROR_ILLEGAL_VALUE;
2592 }
2593 aClientNoContextTakeover = true;
2594 } else if (paramName.EqualsLiteral("server_no_context_takeover")) {
2595 if (!paramValue.IsEmpty()) {
2596 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"server_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
2597 ("WebSocketChannel::ParseWebSocketExtension: parameter "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"server_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
2598 "server_no_context_takeover must not have value, found %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"server_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
2599 PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter "
"server_no_context_takeover must not have value, found %s\n"
, TPromiseFlatString<char>(paramValue).get()); } } while
(0)
;
2600 return NS_ERROR_ILLEGAL_VALUE;
2601 }
2602 if (aServerNoContextTakeover) {
2603 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters server_no_context_takeover\n"); } } while (0)
2604 ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters server_no_context_takeover\n"); } } while (0)
2605 "parameters server_no_context_takeover\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters server_no_context_takeover\n"); } } while (0)
;
2606 return NS_ERROR_ILLEGAL_VALUE;
2607 }
2608 aServerNoContextTakeover = true;
2609 } else if (paramName.EqualsLiteral("client_max_window_bits")) {
2610 if (aClientMaxWindowBits != -1) {
2611 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters client_max_window_bits\n"); } } while (0)
2612 ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters client_max_window_bits\n"); } } while (0)
2613 "parameters client_max_window_bits\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters client_max_window_bits\n"); } } while (0)
;
2614 return NS_ERROR_ILLEGAL_VALUE;
2615 }
2616
2617 if (aMode == eParseServerSide && paramValue.IsEmpty()) {
2618 // Use -2 to indicate that "client_max_window_bits" has been parsed,
2619 // but had no value.
2620 aClientMaxWindowBits = -2;
2621 } else {
2622 nsresult errcode;
2623 aClientMaxWindowBits =
2624 PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode);
2625 if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aClientMaxWindowBits < 8 ||
2626 aClientMaxWindowBits > 15) {
2627 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter client_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
2628 ("WebSocketChannel::ParseWebSocketExtension: found invalid "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter client_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
2629 "parameter client_max_window_bits %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter client_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
2630 PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter client_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
;
2631 return NS_ERROR_ILLEGAL_VALUE;
2632 }
2633 }
2634 } else if (paramName.EqualsLiteral("server_max_window_bits")) {
2635 if (aServerMaxWindowBits != -1) {
2636 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters server_max_window_bits\n"); } } while (0)
2637 ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters server_max_window_bits\n"); } } while (0)
2638 "parameters server_max_window_bits\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple "
"parameters server_max_window_bits\n"); } } while (0)
;
2639 return NS_ERROR_ILLEGAL_VALUE;
2640 }
2641
2642 nsresult errcode;
2643 aServerMaxWindowBits = PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode);
2644 if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aServerMaxWindowBits < 8 ||
2645 aServerMaxWindowBits > 15) {
2646 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter server_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
2647 ("WebSocketChannel::ParseWebSocketExtension: found invalid "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter server_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
2648 "parameter server_max_window_bits %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter server_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
2649 PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid "
"parameter server_max_window_bits %s\n", TPromiseFlatString<
char>(paramValue).get()); } } while (0)
;
2650 return NS_ERROR_ILLEGAL_VALUE;
2651 }
2652 } else {
2653 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown "
"parameter %s\n", TPromiseFlatString<char>(paramName).
get()); } } while (0)
2654 ("WebSocketChannel::ParseWebSocketExtension: found unknown "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown "
"parameter %s\n", TPromiseFlatString<char>(paramName).
get()); } } while (0)
2655 "parameter %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown "
"parameter %s\n", TPromiseFlatString<char>(paramName).
get()); } } while (0)
2656 PromiseFlatCString(paramName).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown "
"parameter %s\n", TPromiseFlatString<char>(paramName).
get()); } } while (0)
;
2657 return NS_ERROR_ILLEGAL_VALUE;
2658 }
2659 }
2660
2661 if (aClientMaxWindowBits == -2) {
2662 aClientMaxWindowBits = -1;
2663 }
2664
2665 return NS_OK;
2666}
2667
2668nsresult WebSocketChannel::HandleExtensions() {
2669 LOG(("WebSocketChannel::HandleExtensions() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions() %p\n"
, this); } } while (0)
;
2670
2671 nsresult rv;
2672 nsAutoCString extensions;
2673
2674 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
2674; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2675
2676 rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Extensions"_ns,
Value stored to 'rv' is never read
2677 extensions);
2678 extensions.CompressWhitespace();
2679 if (extensions.IsEmpty()) {
2680 return NS_OK;
2681 }
2682
2683 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received "
"Sec-WebSocket-Extensions header: %s\n", extensions.get()); }
} while (0)
2684 ("WebSocketChannel::HandleExtensions: received "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received "
"Sec-WebSocket-Extensions header: %s\n", extensions.get()); }
} while (0)
2685 "Sec-WebSocket-Extensions header: %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received "
"Sec-WebSocket-Extensions header: %s\n", extensions.get()); }
} while (0)
2686 extensions.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received "
"Sec-WebSocket-Extensions header: %s\n", extensions.get()); }
} while (0)
;
2687
2688 bool clientNoContextTakeover;
2689 bool serverNoContextTakeover;
2690 int32_t clientMaxWindowBits;
2691 int32_t serverMaxWindowBits;
2692
2693 rv = ParseWebSocketExtension(extensions, eParseClientSide,
2694 clientNoContextTakeover, serverNoContextTakeover,
2695 clientMaxWindowBits, serverMaxWindowBits);
2696 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2697 AbortSession(rv);
2698 return rv;
2699 }
2700
2701 if (clientMaxWindowBits == -1) {
2702 clientMaxWindowBits = 15;
2703 }
2704 if (serverMaxWindowBits == -1) {
2705 serverMaxWindowBits = 15;
2706 }
2707
2708 MutexAutoLock lock(mCompressorMutex);
2709 mPMCECompressor = MakeUnique<PMCECompression>(
2710 clientNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits);
2711 if (mPMCECompressor->Active()) {
2712 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "
"context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n"
, clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,
serverMaxWindowBits); } } while (0)
2713 ("WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "
"context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n"
, clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,
serverMaxWindowBits); } } while (0)
2714 "context takeover, clientMaxWindowBits=%d, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "
"context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n"
, clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,
serverMaxWindowBits); } } while (0)
2715 "serverMaxWindowBits=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "
"context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n"
, clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,
serverMaxWindowBits); } } while (0)
2716 clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "
"context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n"
, clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,
serverMaxWindowBits); } } while (0)
2717 serverMaxWindowBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "
"context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n"
, clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,
serverMaxWindowBits); } } while (0)
;
2718
2719 mNegotiatedExtensions = "permessage-deflate";
2720 } else {
2721 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE "
"compression object\n"); } } while (0)
2722 ("WebSocketChannel::HandleExtensions: Cannot init PMCE "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE "
"compression object\n"); } } while (0)
2723 "compression object\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE "
"compression object\n"); } } while (0)
;
2724 mPMCECompressor = nullptr;
2725 AbortSession(NS_ERROR_UNEXPECTED);
2726 return NS_ERROR_UNEXPECTED;
2727 }
2728
2729 return NS_OK;
2730}
2731
2732void ProcessServerWebSocketExtensions(const nsACString& aExtensions,
2733 nsACString& aNegotiatedExtensions) {
2734 aNegotiatedExtensions.Truncate();
2735
2736 for (const auto& ext :
2737 nsCCharSeparatedTokenizer(aExtensions, ',').ToRange()) {
2738 bool clientNoContextTakeover;
2739 bool serverNoContextTakeover;
2740 int32_t clientMaxWindowBits;
2741 int32_t serverMaxWindowBits;
2742
2743 nsresult rv = ParseWebSocketExtension(
2744 ext, eParseServerSide, clientNoContextTakeover, serverNoContextTakeover,
2745 clientMaxWindowBits, serverMaxWindowBits);
2746 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2747 // Ignore extensions that we can't parse
2748 continue;
2749 }
2750
2751 aNegotiatedExtensions.AssignLiteral("permessage-deflate");
2752 if (clientNoContextTakeover) {
2753 aNegotiatedExtensions.AppendLiteral(";client_no_context_takeover");
2754 }
2755 if (serverNoContextTakeover) {
2756 aNegotiatedExtensions.AppendLiteral(";server_no_context_takeover");
2757 }
2758 if (clientMaxWindowBits != -1) {
2759 aNegotiatedExtensions.AppendLiteral(";client_max_window_bits=");
2760 aNegotiatedExtensions.AppendInt(clientMaxWindowBits);
2761 }
2762 if (serverMaxWindowBits != -1) {
2763 aNegotiatedExtensions.AppendLiteral(";server_max_window_bits=");
2764 aNegotiatedExtensions.AppendInt(serverMaxWindowBits);
2765 }
2766
2767 return;
2768 }
2769}
2770
2771nsresult CalculateWebSocketHashedSecret(const nsACString& aKey,
2772 nsACString& aHash) {
2773 nsresult rv;
2774 nsCString key = aKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_ns;
2775 nsCOMPtr<nsICryptoHash> hasher =
2776 do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv);
2777 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/protocol/websocket/WebSocketChannel.cpp"
, 2777); return rv; } } while (false)
;
2778 rv = hasher->Init(nsICryptoHash::SHA1);
2779 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/protocol/websocket/WebSocketChannel.cpp"
, 2779); return rv; } } while (false)
;
2780 rv = hasher->Update((const uint8_t*)key.BeginWriting(), key.Length());
2781 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/protocol/websocket/WebSocketChannel.cpp"
, 2781); return rv; } } while (false)
;
2782 return hasher->Finish(true, aHash);
2783}
2784
2785nsresult WebSocketChannel::SetupRequest() {
2786 LOG(("WebSocketChannel::SetupRequest() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest() %p\n"
, this); } } while (0)
;
2787
2788 nsresult rv;
2789
2790 if (mLoadGroup) {
2791 rv = mHttpChannel->SetLoadGroup(mLoadGroup);
2792 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/protocol/websocket/WebSocketChannel.cpp"
, 2792); return rv; } } while (false)
;
2793 }
2794
2795 rv = mHttpChannel->SetLoadFlags(
2796 nsIRequest::LOAD_BACKGROUND | nsIRequest::INHIBIT_CACHING |
2797 nsIRequest::LOAD_BYPASS_CACHE | nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
2798 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/protocol/websocket/WebSocketChannel.cpp"
, 2798); return rv; } } while (false)
;
2799
2800 // we never let websockets be blocked by head CSS/JS loads to avoid
2801 // potential deadlock where server generation of CSS/JS requires
2802 // an XHR signal.
2803 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel));
2804 if (cos) {
2805 cos->AddClassFlags(nsIClassOfService::Unblocked);
2806 }
2807
2808 // draft-ietf-hybi-thewebsocketprotocol-07 illustrates Upgrade: websocket
2809 // in lower case, so go with that. It is technically case insensitive.
2810 rv = mChannel->HTTPUpgrade("websocket"_ns, this);
2811 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/protocol/websocket/WebSocketChannel.cpp"
, 2811); return rv; } } while (false)
;
2812
2813 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Version"_ns,
2814 nsLiteralCString(SEC_WEBSOCKET_VERSION"13"),
2815 false);
2816 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2816; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2817
2818 if (!mOrigin.IsEmpty()) {
2819 rv = mHttpChannel->SetRequestHeader("Origin"_ns, mOrigin, false);
2820 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2821 }
2822
2823 if (!mProtocol.IsEmpty()) {
2824 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Protocol"_ns, mProtocol,
2825 true);
2826 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2826; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2827 }
2828
2829 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Extensions"_ns,
2830 "permessage-deflate"_ns, false);
2831 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2831; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2832
2833 uint8_t* secKey;
2834 nsAutoCString secKeyString;
2835
2836 rv = mRandomGenerator->GenerateRandomBytes(16, &secKey);
2837 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/protocol/websocket/WebSocketChannel.cpp"
, 2837); return rv; } } while (false)
;
2838 rv = Base64Encode(reinterpret_cast<const char*>(secKey), 16, secKeyString);
2839 free(secKey);
2840 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2841 return rv;
2842 }
2843
2844 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Key"_ns, secKeyString,
2845 false);
2846 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2846; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2847 LOG(("WebSocketChannel::SetupRequest: client key %s\n", secKeyString.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: client key %s\n"
, secKeyString.get()); } } while (0)
;
2848
2849 // prepare the value we expect to see in
2850 // the sec-websocket-accept response header
2851 rv = CalculateWebSocketHashedSecret(secKeyString, mHashedSecret);
2852 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/protocol/websocket/WebSocketChannel.cpp"
, 2852); return rv; } } while (false)
;
2853 LOG(("WebSocketChannel::SetupRequest: expected server key %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: expected server key %s\n"
, mHashedSecret.get()); } } while (0)
2854 mHashedSecret.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: expected server key %s\n"
, mHashedSecret.get()); } } while (0)
;
2855
2856 mHttpChannelId = mHttpChannel->ChannelId();
2857
2858 return NS_OK;
2859}
2860
2861nsresult WebSocketChannel::DoAdmissionDNS() {
2862 nsresult rv;
2863
2864 nsCString hostName;
2865 rv = mURI->GetHost(hostName);
2866 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/protocol/websocket/WebSocketChannel.cpp"
, 2866); return rv; } } while (false)
;
2867 mAddress = hostName;
2868 nsCString path;
2869 rv = mURI->GetFilePath(path);
2870 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/protocol/websocket/WebSocketChannel.cpp"
, 2870); return rv; } } while (false)
;
2871 mPath = path;
2872 rv = mURI->GetPort(&mPort);
2873 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/protocol/websocket/WebSocketChannel.cpp"
, 2873); return rv; } } while (false)
;
2874 if (mPort == -1) mPort = (mEncrypted ? kDefaultWSSPort : kDefaultWSPort);
2875 nsCOMPtr<nsIDNSService> dns;
2876 dns = mozilla::components::DNS::Service(&rv);
2877 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/protocol/websocket/WebSocketChannel.cpp"
, 2877); return rv; } } while (false)
;
2878 nsCOMPtr<nsIEventTarget> main = GetMainThreadSerialEventTarget();
2879 nsCOMPtr<nsICancelable> cancelable;
2880 rv = dns->AsyncResolveNative(hostName, nsIDNSService::RESOLVE_TYPE_DEFAULT,
2881 nsIDNSService::RESOLVE_DEFAULT_FLAGS, nullptr,
2882 this, main, mLoadInfo->GetOriginAttributes(),
2883 getter_AddRefs(cancelable));
2884 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2885 return rv;
2886 }
2887
2888 MutexAutoLock lock(mMutex);
2889 MOZ_ASSERT(!mCancelable)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCancelable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mCancelable", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable"
")"); do { *((volatile int*)__null) = 2889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2890 mCancelable = std::move(cancelable);
2891 return rv;
2892}
2893
2894nsresult WebSocketChannel::ApplyForAdmission() {
2895 LOG(("WebSocketChannel::ApplyForAdmission() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission() %p\n"
, this); } } while (0)
;
2896
2897 // Websockets has a policy of 1 session at a time being allowed in the
2898 // CONNECTING state per server IP address (not hostname)
2899
2900 // Check to see if a proxy is being used before making DNS call
2901 nsCOMPtr<nsIProtocolProxyService> pps;
2902 pps = mozilla::components::ProtocolProxy::Service();
2903
2904 if (!pps) {
2905 // go straight to DNS
2906 // expect the callback in ::OnLookupComplete
2907 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"
); } } while (0)
2908 "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"
); } } while (0)
;
2909 return DoAdmissionDNS();
2910 }
2911
2912 nsresult rv;
2913 nsCOMPtr<nsICancelable> cancelable;
2914 rv = pps->AsyncResolve(
2915 mHttpChannel,
2916 nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY |
2917 nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
2918 nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
2919 this, nullptr, getter_AddRefs(cancelable));
2920
2921 MutexAutoLock lock(mMutex);
2922 MOZ_ASSERT(!mCancelable)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCancelable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mCancelable", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable"
")"); do { *((volatile int*)__null) = 2922; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2923 mCancelable = std::move(cancelable);
2924 return rv;
2925}
2926
2927// Called after both OnStartRequest and OnTransportAvailable have
2928// executed. This essentially ends the handshake and starts the websockets
2929// protocol state machine.
2930nsresult WebSocketChannel::CallStartWebsocketData() {
2931 LOG(("WebSocketChannel::CallStartWebsocketData() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallStartWebsocketData() %p"
, this); } } while (0)
;
2932 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
2932; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2933
2934 if (mOpenTimer) {
2935 mOpenTimer->Cancel();
2936 mOpenTimer = nullptr;
2937 }
2938
2939 nsCOMPtr<nsIEventTarget> target = GetTargetThread();
2940 if (target && !target->IsOnCurrentThread()) {
2941 return target->Dispatch(
2942 NewRunnableMethod("net::WebSocketChannel::StartWebsocketData", this,
2943 &WebSocketChannel::StartWebsocketData),
2944 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2945 }
2946
2947 return StartWebsocketData();
2948}
2949
2950nsresult WebSocketChannel::StartWebsocketData() {
2951 {
2952 MutexAutoLock lock(mMutex);
2953 LOG(("WebSocketChannel::StartWebsocketData() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData() %p"
, this); } } while (0)
;
2954 MOZ_ASSERT(!mDataStarted, "StartWebsocketData twice")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDataStarted)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDataStarted))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mDataStarted" " ("
"StartWebsocketData twice" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 2954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDataStarted"
") (" "StartWebsocketData twice" ")"); do { *((volatile int*
)__null) = 2954; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2955
2956 if (mStopped) {
2957 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not "
"starting data"); } } while (0)
2958 ("WebSocketChannel::StartWebsocketData channel already closed, not "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not "
"starting data"); } } while (0)
2959 "starting data"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not "
"starting data"); } } while (0)
;
2960 return NS_ERROR_NOT_AVAILABLE;
2961 }
2962 }
2963
2964 RefPtr<WebSocketChannel> self = this;
2965 mIOThread->Dispatch(NS_NewRunnableFunction(
2966 "WebSocketChannel::StartWebsocketData", [self{std::move(self)}] {
2967 LOG(("WebSocketChannel::DoStartWebsocketData() %p", self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStartWebsocketData() %p"
, self.get()); } } while (0)
;
2968
2969 NS_DispatchToMainThread(
2970 NewRunnableMethod("net::WebSocketChannel::NotifyOnStart", self,
2971 &WebSocketChannel::NotifyOnStart),
2972 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2973
2974 nsresult rv = self->mConnection ? self->mConnection->StartReading()
2975 : self->mSocketIn->AsyncWait(
2976 self, 0, 0, self->mIOThread);
2977 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2978 self->AbortSession(rv);
2979 }
2980
2981 if (self->mPingInterval) {
2982 rv = self->StartPinging();
2983 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2984 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, "
"rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while (
0)
2985 "WebSocketChannel::StartWebsocketData Could not start pinging, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, "
"rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while (
0)
2986 "rv=0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, "
"rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while (
0)
2987 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, "
"rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while (
0)
;
2988 self->AbortSession(rv);
2989 }
2990 }
2991 }));
2992
2993 return NS_OK;
2994}
2995
2996void WebSocketChannel::NotifyOnStart() {
2997 LOG(("WebSocketChannel::NotifyOnStart Notifying Listener %p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart Notifying Listener %p"
, mListenerMT ? mListenerMT->mListener.get() : nullptr); }
} while (0)
2998 mListenerMT ? mListenerMT->mListener.get() : nullptr))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart Notifying Listener %p"
, mListenerMT ? mListenerMT->mListener.get() : nullptr); }
} while (0)
;
2999 mDataStarted = true;
3000 if (mListenerMT) {
3001 nsresult rv = mListenerMT->mListener->OnStart(mListenerMT->mContext);
3002 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3003 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart "
"mListenerMT->mListener->OnStart() failed with error 0x%08"
"x", static_cast<uint32_t>(rv)); } } while (0)
3004 ("WebSocketChannel::NotifyOnStart "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart "
"mListenerMT->mListener->OnStart() failed with error 0x%08"
"x", static_cast<uint32_t>(rv)); } } while (0)
3005 "mListenerMT->mListener->OnStart() failed with error 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart "
"mListenerMT->mListener->OnStart() failed with error 0x%08"
"x", static_cast<uint32_t>(rv)); } } while (0)
3006 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart "
"mListenerMT->mListener->OnStart() failed with error 0x%08"
"x", static_cast<uint32_t>(rv)); } } while (0)
;
3007 }
3008 }
3009}
3010
3011nsresult WebSocketChannel::StartPinging() {
3012 LOG(("WebSocketChannel::StartPinging() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartPinging() %p"
, this); } } while (0)
;
3013 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 3013; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3014 MOZ_ASSERT(mPingInterval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPingInterval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPingInterval))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mPingInterval",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval"
")"); do { *((volatile int*)__null) = 3014; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3015 MOZ_ASSERT(!mPingTimer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPingTimer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPingTimer))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mPingTimer", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPingTimer"
")"); do { *((volatile int*)__null) = 3015; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3016
3017 nsresult rv;
3018 rv = NS_NewTimerWithCallback(getter_AddRefs(mPingTimer), this, mPingInterval,
3019 nsITimer::TYPE_ONE_SHOT);
3020 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3021 LOG(("WebSocketChannel will generate ping after %d ms of receive silence\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel will generate ping after %d ms of receive silence\n"
, (uint32_t)mPingInterval); } } while (0)
3022 (uint32_t)mPingInterval))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel will generate ping after %d ms of receive silence\n"
, (uint32_t)mPingInterval); } } while (0)
;
3023 } else {
3024 NS_WARNING("unable to create ping timer. Carrying on.")NS_DebugBreak(NS_DEBUG_WARNING, "unable to create ping timer. Carrying on."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3024)
;
3025 }
3026
3027 return NS_OK;
3028}
3029
3030void WebSocketChannel::ReportConnectionTelemetry(nsresult aStatusCode) {
3031 // 3 bits are used. high bit is for wss, middle bit for failed,
3032 // and low bit for proxy..
3033 // 0 - 7 : ws-ok-plain, ws-ok-proxy, ws-failed-plain, ws-failed-proxy,
3034 // wss-ok-plain, wss-ok-proxy, wss-failed-plain, wss-failed-proxy
3035
3036 bool didProxy = false;
3037
3038 nsCOMPtr<nsIProxyInfo> pi;
3039 nsCOMPtr<nsIProxiedChannel> pc = do_QueryInterface(mChannel);
3040 if (pc) pc->GetProxyInfo(getter_AddRefs(pi));
3041 if (pi) {
3042 nsAutoCString proxyType;
3043 pi->GetType(proxyType);
3044 if (!proxyType.IsEmpty() && !proxyType.EqualsLiteral("direct")) {
3045 didProxy = true;
3046 }
3047 }
3048
3049 uint8_t value =
3050 (mEncrypted ? (1 << 2) : 0) |
3051 (!(mGotUpgradeOK && NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1)
))
) ? (1 << 1) : 0) |
3052 (didProxy ? (1 << 0) : 0);
3053
3054 LOG(("WebSocketChannel::ReportConnectionTelemetry() %p %d", this, value))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReportConnectionTelemetry() %p %d"
, this, value); } } while (0)
;
3055 Telemetry::Accumulate(Telemetry::WEBSOCKETS_HANDSHAKE_TYPE, value);
3056}
3057
3058// nsIDNSListener
3059
3060NS_IMETHODIMPnsresult
3061WebSocketChannel::OnLookupComplete(nsICancelable* aRequest,
3062 nsIDNSRecord* aRecord, nsresult aStatus) {
3063 LOG(("WebSocketChannel::OnLookupComplete() %p [%p %p %" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete() %p [%p %p %"
"x" "]\n", this, aRequest, aRecord, static_cast<uint32_t>
(aStatus)); } } while (0)
3064 aRequest, aRecord, static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete() %p [%p %p %"
"x" "]\n", this, aRequest, aRecord, static_cast<uint32_t>
(aStatus)); } } while (0)
;
3065
3066 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3066; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3067
3068 {
3069 MutexAutoLock lock(mMutex);
3070 mCancelable = nullptr;
3071 }
3072
3073 if (mStopped) {
3074 LOG(("WebSocketChannel::OnLookupComplete: Request Already Stopped\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: Request Already Stopped\n"
); } } while (0)
;
3075 return NS_OK;
3076 }
3077
3078 // These failures are not fatal - we just use the hostname as the key
3079 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
3080 LOG(("WebSocketChannel::OnLookupComplete: No DNS Response\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: No DNS Response\n"
); } } while (0)
;
3081
3082 // set host in case we got here without calling DoAdmissionDNS()
3083 mURI->GetHost(mAddress);
3084 } else {
3085 nsCOMPtr<nsIDNSAddrRecord> record = do_QueryInterface(aRecord);
3086 MOZ_ASSERT(record)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(record)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(record))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("record", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3086); AnnotateMozCrashReason("MOZ_ASSERT" "(" "record" ")"
); do { *((volatile int*)__null) = 3086; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3087 nsresult rv = record->GetNextAddrAsString(mAddress);
3088 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3089 LOG(("WebSocketChannel::OnLookupComplete: Failed GetNextAddr\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: Failed GetNextAddr\n"
); } } while (0)
;
3090 }
3091 }
3092
3093 LOG(("WebSocket OnLookupComplete: Proceeding to ConditionallyConnect\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnLookupComplete: Proceeding to ConditionallyConnect\n"
); } } while (0)
;
3094 nsWSAdmissionManager::ConditionallyConnect(this);
3095
3096 return NS_OK;
3097}
3098
3099// nsIProtocolProxyCallback
3100NS_IMETHODIMPnsresult
3101WebSocketChannel::OnProxyAvailable(nsICancelable* aRequest,
3102 nsIChannel* aChannel, nsIProxyInfo* pi,
3103 nsresult status) {
3104 {
3105 MutexAutoLock lock(mMutex);
3106 MOZ_ASSERT(!mCancelable || (aRequest == mCancelable))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCancelable || (aRequest == mCancelable))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mCancelable || (aRequest == mCancelable)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mCancelable || (aRequest == mCancelable)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable || (aRequest == mCancelable)"
")"); do { *((volatile int*)__null) = 3106; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3107 mCancelable = nullptr;
3108 }
3109
3110 if (mStopped) {
3111 LOG(("WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n"
, this); } } while (0)
3112 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n"
, this); } } while (0)
;
3113 return NS_OK;
3114 }
3115
3116 nsAutoCString type;
3117 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && pi && NS_SUCCEEDED(pi->GetType(type))((bool)(__builtin_expect(!!(!NS_FAILED_impl(pi->GetType(type
))), 1)))
&&
3118 !type.EqualsLiteral("direct")) {
3119 LOG(("WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n"
, this); } } while (0)
3120 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n"
, this); } } while (0)
;
3121 // call DNS callback directly without DNS resolver
3122 OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE);
3123 } else {
3124 LOG(("WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n"
, this); } } while (0)
3125 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n"
, this); } } while (0)
;
3126 nsresult rv = DoAdmissionDNS();
3127 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3128 LOG(("WebSocket OnProxyAvailable [%p] DNS lookup failed\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] DNS lookup failed\n"
, this); } } while (0)
;
3129 // call DNS callback directly without DNS resolver
3130 OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE);
3131 }
3132 }
3133
3134 // notify listener of OnProxyAvailable
3135 LOG(("WebSocketChannel::OnProxyAvailable Notifying Listener %p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable Notifying Listener %p"
, mListenerMT ? mListenerMT->mListener.get() : nullptr); }
} while (0)
3136 mListenerMT ? mListenerMT->mListener.get() : nullptr))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable Notifying Listener %p"
, mListenerMT ? mListenerMT->mListener.get() : nullptr); }
} while (0)
;
3137 nsresult rv;
3138 nsCOMPtr<nsIProtocolProxyCallback> ppc(
3139 do_QueryInterface(mListenerMT->mListener, &rv));
3140 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3141 rv = ppc->OnProxyAvailable(aRequest, aChannel, pi, status);
3142 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3143 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify"
" failed with error 0x%08" "x", static_cast<uint32_t>(
rv)); } } while (0)
3144 ("WebSocketChannel::OnProxyAvailable notify"do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify"
" failed with error 0x%08" "x", static_cast<uint32_t>(
rv)); } } while (0)
3145 " failed with error 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify"
" failed with error 0x%08" "x", static_cast<uint32_t>(
rv)); } } while (0)
3146 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify"
" failed with error 0x%08" "x", static_cast<uint32_t>(
rv)); } } while (0)
;
3147 }
3148 }
3149
3150 return NS_OK;
3151}
3152
3153// nsIInterfaceRequestor
3154
3155NS_IMETHODIMPnsresult
3156WebSocketChannel::GetInterface(const nsIID& iid, void** result) {
3157 LOG(("WebSocketChannel::GetInterface() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GetInterface() %p\n"
, this); } } while (0)
;
3158
3159 if (iid.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::COMTypeInfo<nsIChannelEventSink, void
>::kIID)
)) {
3160 return QueryInterface(iid, result);
3161 }
3162
3163 if (mCallbacks) return mCallbacks->GetInterface(iid, result);
3164
3165 return NS_ERROR_NO_INTERFACE;
3166}
3167
3168// nsIChannelEventSink
3169
3170NS_IMETHODIMPnsresult
3171WebSocketChannel::AsyncOnChannelRedirect(
3172 nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t flags,
3173 nsIAsyncVerifyRedirectCallback* callback) {
3174 LOG(("WebSocketChannel::AsyncOnChannelRedirect() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOnChannelRedirect() %p\n"
, this); } } while (0)
;
3175
3176 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3176; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3177
3178 nsresult rv;
3179
3180 nsCOMPtr<nsIURI> newuri;
3181 rv = newChannel->GetURI(getter_AddRefs(newuri));
3182 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/protocol/websocket/WebSocketChannel.cpp"
, 3182); return rv; } } while (false)
;
3183
3184 // newuri is expected to be http or https
3185 bool newuriIsHttps = newuri->SchemeIs("https");
3186
3187 // allow insecure->secure redirects for HTTP Strict Transport Security (from
3188 // ws://FOO to https://FOO (mapped to wss://FOO)
3189 if (!(flags & (nsIChannelEventSink::REDIRECT_INTERNAL |
3190 nsIChannelEventSink::REDIRECT_STS_UPGRADE))) {
3191 nsAutoCString newSpec;
3192 rv = newuri->GetSpec(newSpec);
3193 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/protocol/websocket/WebSocketChannel.cpp"
, 3193); return rv; } } while (false)
;
3194
3195 LOG(("WebSocketChannel: Redirect to %s denied by configuration\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s denied by configuration\n"
, newSpec.get()); } } while (0)
3196 newSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s denied by configuration\n"
, newSpec.get()); } } while (0)
;
3197 return NS_ERROR_FAILURE;
3198 }
3199
3200 if (mEncrypted && !newuriIsHttps) {
3201 nsAutoCString spec;
3202 if (NS_SUCCEEDED(newuri->GetSpec(spec))((bool)(__builtin_expect(!!(!NS_FAILED_impl(newuri->GetSpec
(spec))), 1)))
) {
3203 LOG(("WebSocketChannel: Redirect to %s violates encryption rule\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s violates encryption rule\n"
, spec.get()); } } while (0)
3204 spec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s violates encryption rule\n"
, spec.get()); } } while (0)
;
3205 }
3206 return NS_ERROR_FAILURE;
3207 }
3208
3209 nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(newChannel, &rv);
3210 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3211 LOG(("WebSocketChannel: Redirect could not QI to HTTP\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not QI to HTTP\n"
); } } while (0)
;
3212 return rv;
3213 }
3214
3215 nsCOMPtr<nsIHttpChannelInternal> newUpgradeChannel =
3216 do_QueryInterface(newChannel, &rv);
3217
3218 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3219 LOG(("WebSocketChannel: Redirect could not QI to HTTP Upgrade\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not QI to HTTP Upgrade\n"
); } } while (0)
;
3220 return rv;
3221 }
3222
3223 // The redirect is likely OK
3224
3225 newChannel->SetNotificationCallbacks(this);
3226
3227 mEncrypted = newuriIsHttps;
3228 rv = NS_MutateURI(newuri)
3229 .SetScheme(mEncrypted ? "wss"_ns : "ws"_ns)
3230 .Finalize(mURI);
3231
3232 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3233 LOG(("WebSocketChannel: Could not set the proper scheme\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Could not set the proper scheme\n"
); } } while (0)
;
3234 return rv;
3235 }
3236
3237 mHttpChannel = newHttpChannel;
3238 mChannel = newUpgradeChannel;
3239 rv = SetupRequest();
3240 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3241 LOG(("WebSocketChannel: Redirect could not SetupRequest()\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not SetupRequest()\n"
); } } while (0)
;
3242 return rv;
3243 }
3244
3245 // Redirected-to URI may need to be delayed by 1-connecting-per-host and
3246 // delay-after-fail algorithms. So hold off calling OnRedirectVerifyCallback
3247 // until BeginOpen, when we know it's OK to proceed with new channel.
3248 mRedirectCallback = callback;
3249
3250 // Mark old channel as successfully connected so we'll clear any FailDelay
3251 // associated with the old URI. Note: no need to also call OnStopSession:
3252 // it's a no-op for successful, already-connected channels.
3253 nsWSAdmissionManager::OnConnected(this);
3254
3255 // ApplyForAdmission as if we were starting from fresh...
3256 mAddress.Truncate();
3257 mOpenedHttpChannel = false;
3258 rv = ApplyForAdmission();
3259 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3260 LOG(("WebSocketChannel: Redirect failed due to DNS failure\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect failed due to DNS failure\n"
); } } while (0)
;
3261 mRedirectCallback = nullptr;
3262 return rv;
3263 }
3264
3265 return NS_OK;
3266}
3267
3268// nsITimerCallback
3269
3270NS_IMETHODIMPnsresult
3271WebSocketChannel::Notify(nsITimer* timer) {
3272 LOG(("WebSocketChannel::Notify() %p [%p]\n", this, timer))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Notify() %p [%p]\n"
, this, timer); } } while (0)
;
3273
3274 if (timer == mCloseTimer) {
3275 MOZ_ASSERT(mClientClosed, "Close Timeout without local close")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mClientClosed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mClientClosed))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mClientClosed" " ("
"Close Timeout without local close" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientClosed"
") (" "Close Timeout without local close" ")"); do { *((volatile
int*)__null) = 3275; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3276 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 3276; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3277
3278 mCloseTimer = nullptr;
3279 if (mStopped || mServerClosed) { /* no longer relevant */
3280 return NS_OK;
3281 }
3282
3283 LOG(("WebSocketChannel:: Expecting Server Close - Timed Out\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Expecting Server Close - Timed Out\n"
); } } while (0)
;
3284 AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL);
3285 } else if (timer == mOpenTimer) {
3286 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3286; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3287
3288 mOpenTimer = nullptr;
3289 LOG(("WebSocketChannel:: Connection Timed Out\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Connection Timed Out\n"
); } } while (0)
;
3290 if (mStopped || mServerClosed) { /* no longer relevant */
3291 return NS_OK;
3292 }
3293
3294 AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL);
3295 MOZ_PUSH_IGNORE_THREAD_SAFETYGCC diagnostic push GCC diagnostic ignored "-Wthread-safety"
3296 // mReconnectDelayTimer is only modified on MainThread, we can read it
3297 // without a lock, but ONLY if we're on MainThread! And if we're not
3298 // on MainThread, it can't be mReconnectDelayTimer
3299 } else if (NS_IsMainThread() && timer == mReconnectDelayTimer) {
3300 MOZ_POP_THREAD_SAFETYGCC diagnostic pop
3301 MOZ_ASSERT(mConnecting == CONNECTING_DELAYED,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mConnecting == CONNECTING_DELAYED)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mConnecting == CONNECTING_DELAYED
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mConnecting == CONNECTING_DELAYED" " (" "woke up from delay w/o being delayed?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED"
") (" "woke up from delay w/o being delayed?" ")"); do { *((
volatile int*)__null) = 3302; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
3302 "woke up from delay w/o being delayed?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mConnecting == CONNECTING_DELAYED)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mConnecting == CONNECTING_DELAYED
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mConnecting == CONNECTING_DELAYED" " (" "woke up from delay w/o being delayed?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED"
") (" "woke up from delay w/o being delayed?" ")"); do { *((
volatile int*)__null) = 3302; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
3303
3304 {
3305 MutexAutoLock lock(mMutex);
3306 mReconnectDelayTimer = nullptr;
3307 }
3308 LOG(("WebSocketChannel: connecting [this=%p] after reconnect delay", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: connecting [this=%p] after reconnect delay"
, this); } } while (0)
;
3309 BeginOpen(false);
3310 } else if (timer == mPingTimer) {
3311 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 3311; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3312
3313 if (mClientClosed || mServerClosed || mRequestedClose) {
3314 // no point in worrying about ping now
3315 mPingTimer = nullptr;
3316 return NS_OK;
3317 }
3318
3319 if (!mPingOutstanding) {
3320 // Ping interval must be non-null or PING was forced by OnNetworkChanged()
3321 MOZ_ASSERT(mPingInterval || mPingForced)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPingInterval || mPingForced)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPingInterval || mPingForced
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mPingInterval || mPingForced", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval || mPingForced"
")"); do { *((volatile int*)__null) = 3321; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3322 LOG(("nsWebSocketChannel:: Generating Ping\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Generating Ping\n"
); } } while (0)
;
3323 mPingOutstanding = 1;
3324 mPingForced = false;
3325 mPingTimer->InitWithCallback(this, mPingResponseTimeout,
3326 nsITimer::TYPE_ONE_SHOT);
3327 GeneratePing();
3328 } else {
3329 LOG(("nsWebSocketChannel:: Timed out Ping\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Timed out Ping\n"
); } } while (0)
;
3330 mPingTimer = nullptr;
3331 AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL);
3332 }
3333 } else if (timer == mLingeringCloseTimer) {
3334 LOG(("WebSocketChannel:: Lingering Close Timer"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Lingering Close Timer"
); } } while (0)
;
3335 CleanupConnection();
3336 } else {
3337 MOZ_ASSERT(0, "Unknown Timer")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("0" " (" "Unknown Timer" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ") (" "Unknown Timer"
")"); do { *((volatile int*)__null) = 3337; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3338 }
3339
3340 return NS_OK;
3341}
3342
3343// nsINamed
3344
3345NS_IMETHODIMPnsresult
3346WebSocketChannel::GetName(nsACString& aName) {
3347 aName.AssignLiteral("WebSocketChannel");
3348 return NS_OK;
3349}
3350
3351// nsIWebSocketChannel
3352
3353NS_IMETHODIMPnsresult
3354WebSocketChannel::GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) {
3355 LOG(("WebSocketChannel::GetSecurityInfo() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GetSecurityInfo() %p\n"
, this); } } while (0)
;
3356 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3356); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3356; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3357
3358 *aSecurityInfo = nullptr;
3359
3360 if (mConnection) {
3361 nsresult rv = mConnection->GetSecurityInfo(aSecurityInfo);
3362 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3363 return rv;
3364 }
3365 return NS_OK;
3366 }
3367
3368 if (mTransport) {
3369 nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
3370 nsresult rv =
3371 mTransport->GetTlsSocketControl(getter_AddRefs(tlsSocketControl));
3372 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3373 return rv;
3374 }
3375 nsCOMPtr<nsITransportSecurityInfo> securityInfo(
3376 do_QueryInterface(tlsSocketControl));
3377 if (securityInfo) {
3378 securityInfo.forget(aSecurityInfo);
3379 }
3380 }
3381 return NS_OK;
3382}
3383
3384NS_IMETHODIMPnsresult
3385WebSocketChannel::AsyncOpen(nsIURI* aURI, const nsACString& aOrigin,
3386 JS::Handle<JS::Value> aOriginAttributes,
3387 uint64_t aInnerWindowID,
3388 nsIWebSocketListener* aListener,
3389 nsISupports* aContext, JSContext* aCx) {
3390 OriginAttributes attrs;
3391 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
3392 return NS_ERROR_INVALID_ARG;
3393 }
3394 return AsyncOpenNative(aURI, aOrigin, attrs, aInnerWindowID, aListener,
3395 aContext);
3396}
3397
3398NS_IMETHODIMPnsresult
3399WebSocketChannel::AsyncOpenNative(nsIURI* aURI, const nsACString& aOrigin,
3400 const OriginAttributes& aOriginAttributes,
3401 uint64_t aInnerWindowID,
3402 nsIWebSocketListener* aListener,
3403 nsISupports* aContext) {
3404 LOG(("WebSocketChannel::AsyncOpen() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() %p\n"
, this); } } while (0)
;
3405
3406 aOriginAttributes.CreateSuffix(mOriginSuffix);
3407
3408 if (!NS_IsMainThread()) {
3409 MOZ_ASSERT(false, "not main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "not main thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"not main thread" ")"); do { *((volatile int*)__null) = 3409
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3410 LOG(("WebSocketChannel::AsyncOpen() called off the main thread"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() called off the main thread"
); } } while (0)
;
3411 return NS_ERROR_UNEXPECTED;
3412 }
3413
3414 if ((!aURI && !mIsServerSide) || !aListener) {
3415 LOG(("WebSocketChannel::AsyncOpen() Uri or Listener null"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() Uri or Listener null"
); } } while (0)
;
3416 return NS_ERROR_UNEXPECTED;
3417 }
3418
3419 if (mListenerMT || mWasOpened) return NS_ERROR_ALREADY_OPENED;
3420
3421 nsresult rv;
3422
3423 // Ensure target thread is set if RetargetDeliveryTo isn't called
3424 {
3425 auto lock = mTargetThread.Lock();
3426 if (!lock.ref()) {
3427 lock.ref() = GetMainThreadSerialEventTarget();
3428 }
3429 }
3430
3431 mIOThread = mozilla::components::SocketTransport::Service(&rv);
3432 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3433 NS_WARNING("unable to continue without socket transport service")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without socket transport service"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3433)
;
3434 return rv;
3435 }
3436
3437 nsCOMPtr<nsIPrefBranch> prefService;
3438 prefService = mozilla::components::Preferences::Service();
3439
3440 if (prefService) {
3441 int32_t intpref;
3442 rv =
3443 prefService->GetIntPref("network.websocket.max-message-size", &intpref);
3444 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3445 mMaxMessageSize = std::clamp(intpref, 1024, INT32_MAX(2147483647));
3446 }
3447 rv = prefService->GetIntPref("network.websocket.timeout.close", &intpref);
3448 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3449 mCloseTimeout = std::clamp(intpref, 1, 1800) * 1000;
3450 }
3451 rv = prefService->GetIntPref("network.websocket.timeout.open", &intpref);
3452 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3453 mOpenTimeout = std::clamp(intpref, 1, 1800) * 1000;
3454 }
3455 rv = prefService->GetIntPref("network.websocket.timeout.ping.request",
3456 &intpref);
3457 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingInterval) {
3458 mPingInterval = std::clamp(intpref, 0, 86400) * 1000;
3459 }
3460 rv = prefService->GetIntPref("network.websocket.timeout.ping.response",
3461 &intpref);
3462 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingTimeout) {
3463 mPingResponseTimeout = std::clamp(intpref, 1, 3600) * 1000;
3464 }
3465 rv = prefService->GetIntPref("network.websocket.max-connections", &intpref);
3466 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3467 mMaxConcurrentConnections = std::clamp(intpref, 1, 0xffff);
3468 }
3469 }
3470
3471 int32_t sessionCount = -1;
3472 nsWSAdmissionManager::GetSessionCount(sessionCount);
3473 if (sessionCount >= 0) {
3474 LOG(("WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n"
, this, sessionCount, mMaxConcurrentConnections); } } while (
0)
3475 sessionCount, mMaxConcurrentConnections))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n"
, this, sessionCount, mMaxConcurrentConnections); } } while (
0)
;
3476 }
3477
3478 if (sessionCount >= mMaxConcurrentConnections) {
3479 LOG(("WebSocketChannel: max concurrency %d exceeded (%d)",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: max concurrency %d exceeded (%d)"
, mMaxConcurrentConnections, sessionCount); } } while (0)
3480 mMaxConcurrentConnections, sessionCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: max concurrency %d exceeded (%d)"
, mMaxConcurrentConnections, sessionCount); } } while (0)
;
3481
3482 // WebSocket connections are expected to be long lived, so return
3483 // an error here instead of queueing
3484 return NS_ERROR_SOCKET_CREATE_FAILED;
3485 }
3486
3487 mInnerWindowID = aInnerWindowID;
3488 mOriginalURI = aURI;
3489 mURI = mOriginalURI;
3490 mOrigin = aOrigin;
3491
3492 if (mIsServerSide) {
3493 // IncrementSessionCount();
3494 mWasOpened = 1;
3495 mListenerMT = new ListenerAndContextContainer(aListener, aContext);
3496 rv = mServerTransportProvider->SetListener(this);
3497 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3497); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 3497; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3498 mServerTransportProvider = nullptr;
3499
3500 return NS_OK;
3501 }
3502
3503 mURI->GetHostPort(mHost);
3504
3505 mRandomGenerator = mozilla::components::RandomGenerator::Service(&rv);
3506 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3507 NS_WARNING("unable to continue without random number generator")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without random number generator"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3507)
;
3508 return rv;
3509 }
3510
3511 nsCOMPtr<nsIURI> localURI;
3512 nsCOMPtr<nsIChannel> localChannel;
3513
3514 rv = NS_MutateURI(mURI)
3515 .SetScheme(mEncrypted ? "https"_ns : "http"_ns)
3516 .Finalize(localURI);
3517 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/protocol/websocket/WebSocketChannel.cpp"
, 3517); return rv; } } while (false)
;
3518
3519 nsCOMPtr<nsIIOService> ioService;
3520 ioService = mozilla::components::IO::Service(&rv);
3521 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3522 NS_WARNING("unable to continue without io service")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without io service"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3522)
;
3523 return rv;
3524 }
3525
3526 // Ideally we'd call newChannelFromURIWithLoadInfo here, but that doesn't
3527 // allow setting proxy uri/flags
3528 rv = ioService->NewChannelFromURIWithProxyFlags(
3529 localURI, mURI,
3530 nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY |
3531 nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
3532 nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
3533 mLoadInfo->LoadingNode(), mLoadInfo->GetLoadingPrincipal(),
3534 mLoadInfo->TriggeringPrincipal(), mLoadInfo->GetSecurityFlags(),
3535 mLoadInfo->InternalContentPolicyType(), getter_AddRefs(localChannel));
3536 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/protocol/websocket/WebSocketChannel.cpp"
, 3536); return rv; } } while (false)
;
3537
3538 // Please note that we still call SetLoadInfo on the channel because
3539 // we want the same instance of the loadInfo to be set on the channel.
3540 rv = localChannel->SetLoadInfo(mLoadInfo);
3541 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/protocol/websocket/WebSocketChannel.cpp"
, 3541); return rv; } } while (false)
;
3542
3543 // Pass most GetInterface() requests through to our instantiator, but handle
3544 // nsIChannelEventSink in this object in order to deal with redirects
3545 localChannel->SetNotificationCallbacks(this);
3546
3547 class MOZ_STACK_CLASS CleanUpOnFailure {
3548 public:
3549 explicit CleanUpOnFailure(WebSocketChannel* aWebSocketChannel)
3550 : mWebSocketChannel(aWebSocketChannel) {}
3551
3552 ~CleanUpOnFailure() {
3553 if (!mWebSocketChannel->mWasOpened) {
3554 mWebSocketChannel->mChannel = nullptr;
3555 mWebSocketChannel->mHttpChannel = nullptr;
3556 }
3557 }
3558
3559 WebSocketChannel* mWebSocketChannel;
3560 };
3561
3562 CleanUpOnFailure cuof(this);
3563
3564 mChannel = do_QueryInterface(localChannel, &rv);
3565 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/protocol/websocket/WebSocketChannel.cpp"
, 3565); return rv; } } while (false)
;
3566
3567 mHttpChannel = do_QueryInterface(localChannel, &rv);
3568 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/protocol/websocket/WebSocketChannel.cpp"
, 3568); return rv; } } while (false)
;
3569
3570 rv = SetupRequest();
3571 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3572
3573 mPrivateBrowsing = NS_UsePrivateBrowsing(localChannel);
3574
3575 if (mConnectionLogService && !mPrivateBrowsing) {
3576 mConnectionLogService->AddHost(mHost, mSerial,
3577 BaseWebSocketChannel::mEncrypted);
3578 }
3579
3580 rv = ApplyForAdmission();
3581 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3582
3583 // Register for prefs change notifications
3584 nsCOMPtr<nsIObserverService> observerService =
3585 mozilla::services::GetObserverService();
3586 if (!observerService) {
3587 NS_WARNING("failed to get observer service")NS_DebugBreak(NS_DEBUG_WARNING, "failed to get observer service"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3587)
;
3588 return NS_ERROR_FAILURE;
3589 }
3590
3591 rv = observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC"network:link-status-changed", false);
3592 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3592)
) {
3593 return rv;
3594 }
3595
3596 // Only set these if the open was successful:
3597 //
3598 mWasOpened = 1;
3599 mListenerMT = new ListenerAndContextContainer(aListener, aContext);
3600 IncrementSessionCount();
3601
3602 return rv;
3603}
3604
3605NS_IMETHODIMPnsresult
3606WebSocketChannel::Close(uint16_t code, const nsACString& reason) {
3607 LOG(("WebSocketChannel::Close() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() %p\n"
, this); } } while (0)
;
3608 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3608; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3609
3610 {
3611 MutexAutoLock lock(mMutex);
3612
3613 if (mRequestedClose) {
3614 return NS_OK;
3615 }
3616
3617 if (mStopped) {
3618 return NS_ERROR_NOT_AVAILABLE;
3619 }
3620
3621 // The API requires the UTF-8 string to be 123 or less bytes
3622 if (reason.Length() > 123) return NS_ERROR_ILLEGAL_VALUE;
3623
3624 mRequestedClose = true;
3625 mScriptCloseReason = reason;
3626 mScriptCloseCode = code;
3627
3628 if (mDataStarted) {
3629 return mIOThread->Dispatch(
3630 new OutboundEnqueuer(this,
3631 new OutboundMessage(kMsgTypeFin, VoidCString())),
3632 nsIEventTarget::DISPATCH_NORMAL);
3633 }
3634
3635 mStopped = true;
3636 }
3637
3638 nsresult rv;
3639 if (code == CLOSE_GOING_AWAY) {
3640 // Not an error: for example, tab has closed or navigated away
3641 LOG(("WebSocketChannel::Close() GOING_AWAY without transport."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() GOING_AWAY without transport."
); } } while (0)
;
3642 rv = NS_OK;
3643 } else {
3644 LOG(("WebSocketChannel::Close() without transport - error."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() without transport - error."
); } } while (0)
;
3645 rv = NS_ERROR_NOT_CONNECTED;
3646 }
3647
3648 DoStopSession(rv);
3649 return rv;
3650}
3651
3652NS_IMETHODIMPnsresult
3653WebSocketChannel::SendMsg(const nsACString& aMsg) {
3654 LOG(("WebSocketChannel::SendMsg() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendMsg() %p\n"
, this); } } while (0)
;
3655
3656 return SendMsgCommon(aMsg, false, aMsg.Length());
3657}
3658
3659NS_IMETHODIMPnsresult
3660WebSocketChannel::SendBinaryMsg(const nsACString& aMsg) {
3661 LOG(("WebSocketChannel::SendBinaryMsg() %p len=%zu\n", this, aMsg.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendBinaryMsg() %p len=%zu\n"
, this, aMsg.Length()); } } while (0)
;
3662 return SendMsgCommon(aMsg, true, aMsg.Length());
3663}
3664
3665NS_IMETHODIMPnsresult
3666WebSocketChannel::SendBinaryStream(nsIInputStream* aStream, uint32_t aLength) {
3667 LOG(("WebSocketChannel::SendBinaryStream() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendBinaryStream() %p\n"
, this); } } while (0)
;
3668
3669 return SendMsgCommon(VoidCString(), true, aLength, aStream);
3670}
3671
3672nsresult WebSocketChannel::SendMsgCommon(const nsACString& aMsg, bool aIsBinary,
3673 uint32_t aLength,
3674 nsIInputStream* aStream) {
3675 MOZ_ASSERT(IsOnTargetThread(), "not target thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnTargetThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsOnTargetThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsOnTargetThread()"
" (" "not target thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnTargetThread()"
") (" "not target thread" ")"); do { *((volatile int*)__null
) = 3675; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3676
3677 if (!mDataStarted) {
3678 LOG(("WebSocketChannel:: Error: data not started yet\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: data not started yet\n"
); } } while (0)
;
3679 return NS_ERROR_UNEXPECTED;
3680 }
3681
3682 if (mRequestedClose) {
3683 LOG(("WebSocketChannel:: Error: send when closed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: send when closed\n"
); } } while (0)
;
3684 return NS_ERROR_UNEXPECTED;
3685 }
3686
3687 if (mStopped) {
3688 LOG(("WebSocketChannel:: Error: send when stopped\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: send when stopped\n"
); } } while (0)
;
3689 return NS_ERROR_NOT_CONNECTED;
3690 }
3691
3692 MOZ_ASSERT(mMaxMessageSize >= 0, "max message size negative")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMaxMessageSize >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMaxMessageSize >= 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("mMaxMessageSize >= 0"
" (" "max message size negative" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3692); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMaxMessageSize >= 0"
") (" "max message size negative" ")"); do { *((volatile int
*)__null) = 3692; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3693 if (aLength > static_cast<uint32_t>(mMaxMessageSize)) {
3694 LOG(("WebSocketChannel:: Error: message too big\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: message too big\n"
); } } while (0)
;
3695 return NS_ERROR_FILE_TOO_BIG;
3696 }
3697
3698 if (mConnectionLogService && !mPrivateBrowsing) {
3699 mConnectionLogService->NewMsgSent(mHost, mSerial, aLength);
3700 LOG(("Added new msg sent for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new msg sent for %s"
, mHost.get()); } } while (0)
;
3701 }
3702
3703 return mIOThread->Dispatch(
3704 aStream
3705 ? new OutboundEnqueuer(this, new OutboundMessage(aStream, aLength))
3706 : new OutboundEnqueuer(
3707 this,
3708 new OutboundMessage(
3709 aIsBinary ? kMsgTypeBinaryString : kMsgTypeString, aMsg)),
3710 nsIEventTarget::DISPATCH_NORMAL);
3711}
3712
3713// nsIHttpUpgradeListener
3714
3715NS_IMETHODIMPnsresult
3716WebSocketChannel::OnTransportAvailable(nsISocketTransport* aTransport,
3717 nsIAsyncInputStream* aSocketIn,
3718 nsIAsyncOutputStream* aSocketOut) {
3719 if (!NS_IsMainThread()) {
3720 return NS_DispatchToMainThread(
3721 new CallOnTransportAvailable(this, aTransport, aSocketIn, aSocketOut));
3722 }
3723
3724 LOG(("WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n"
, this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK); } }
while (0)
3725 this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n"
, this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK); } }
while (0)
;
3726
3727 if (mStopped) {
3728 LOG(("WebSocketChannel::OnTransportAvailable: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Already stopped"
); } } while (0)
;
3729 return NS_OK;
3730 }
3731
3732 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3732; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3733 MOZ_ASSERT(!mRecvdHttpUpgradeTransport, "OTA duplicated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport"
" (" "OTA duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OTA duplicated" ")"); do { *((volatile int*)__null) =
3733; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3734 MOZ_ASSERT(aSocketIn, "OTA with invalid socketIn")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSocketIn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSocketIn))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aSocketIn" " (" "OTA with invalid socketIn"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSocketIn" ") ("
"OTA with invalid socketIn" ")"); do { *((volatile int*)__null
) = 3734; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3735
3736 mTransport = aTransport;
3737 mSocketIn = aSocketIn;
3738 mSocketOut = aSocketOut;
3739
3740 nsresult rv;
3741 rv = mTransport->SetEventSink(nullptr, nullptr);
3742 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3743 rv = mTransport->SetSecurityCallbacks(this);
3744 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3745
3746 return OnTransportAvailableInternal();
3747}
3748
3749NS_IMETHODIMPnsresult
3750WebSocketChannel::OnWebSocketConnectionAvailable(
3751 WebSocketConnectionBase* aConnection) {
3752 if (!NS_IsMainThread()) {
3753 RefPtr<WebSocketChannel> self = this;
3754 RefPtr<WebSocketConnectionBase> connection = aConnection;
3755 return NS_DispatchToMainThread(NS_NewRunnableFunction(
3756 "WebSocketChannel::OnWebSocketConnectionAvailable",
3757 [self, connection]() {
3758 self->OnWebSocketConnectionAvailable(connection);
3759 }));
3760 }
3761
3762 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "
"rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while
(0)
3763 ("WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "
"rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while
(0)
3764 "rcvdonstart=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "
"rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while
(0)
3765 this, aConnection, mGotUpgradeOK))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "
"rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while
(0)
;
3766
3767 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3767; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3768 MOZ_ASSERT(!mRecvdHttpUpgradeTransport,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport"
" (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3769; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3769 "OnWebSocketConnectionAvailable duplicated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport"
" (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3769; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3770 MOZ_ASSERT(aConnection)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aConnection)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aConnection))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aConnection", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aConnection"
")"); do { *((volatile int*)__null) = 3770; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3771
3772 if (mStopped) {
3773 LOG(("WebSocketChannel::OnWebSocketConnectionAvailable: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable: Already stopped"
); } } while (0)
;
3774 aConnection->Close();
3775 return NS_OK;
3776 }
3777
3778 nsresult rv = aConnection->Init(this);
3779 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3780 return rv;
3781 }
3782
3783 mConnection = aConnection;
3784 // Note: mIOThread will be IPDL background thread.
3785 mConnection->GetIoTarget(getter_AddRefs(mIOThread));
3786 return OnTransportAvailableInternal();
3787}
3788
3789nsresult WebSocketChannel::OnTransportAvailableInternal() {
3790 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3790; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3791 MOZ_ASSERT(!mRecvdHttpUpgradeTransport,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport"
" (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3792; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3792 "OnWebSocketConnectionAvailable duplicated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport"
" (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3792; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3793 MOZ_ASSERT(mSocketIn || mConnection)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSocketIn || mConnection)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSocketIn || mConnection))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mSocketIn || mConnection"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSocketIn || mConnection"
")"); do { *((volatile int*)__null) = 3793; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3794
3795 mRecvdHttpUpgradeTransport = 1;
3796 if (mGotUpgradeOK) {
3797 // We're now done CONNECTING, which means we can now open another,
3798 // perhaps parallel, connection to the same host if one
3799 // is pending
3800 nsWSAdmissionManager::OnConnected(this);
3801
3802 return CallStartWebsocketData();
3803 }
3804
3805 if (mIsServerSide) {
3806 if (!mNegotiatedExtensions.IsEmpty()) {
3807 bool clientNoContextTakeover;
3808 bool serverNoContextTakeover;
3809 int32_t clientMaxWindowBits;
3810 int32_t serverMaxWindowBits;
3811
3812 nsresult rv = ParseWebSocketExtension(
3813 mNegotiatedExtensions, eParseServerSide, clientNoContextTakeover,
3814 serverNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits);
3815 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), "illegal value provided by server")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"illegal value provided by server" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3815); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "illegal value provided by server" ")"); do { *((volatile
int*)__null) = 3815; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3816
3817 if (clientMaxWindowBits == -1) {
3818 clientMaxWindowBits = 15;
3819 }
3820 if (serverMaxWindowBits == -1) {
3821 serverMaxWindowBits = 15;
3822 }
3823
3824 MutexAutoLock lock(mCompressorMutex);
3825 mPMCECompressor = MakeUnique<PMCECompression>(
3826 serverNoContextTakeover, serverMaxWindowBits, clientMaxWindowBits);
3827 if (mPMCECompressor->Active()) {
3828 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "
"context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n"
, serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,
clientMaxWindowBits); } } while (0)
3829 ("WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "
"context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n"
, serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,
clientMaxWindowBits); } } while (0)
3830 "context takeover, serverMaxWindowBits=%d, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "
"context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n"
, serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,
clientMaxWindowBits); } } while (0)
3831 "clientMaxWindowBits=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "
"context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n"
, serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,
clientMaxWindowBits); } } while (0)
3832 serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "
"context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n"
, serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,
clientMaxWindowBits); } } while (0)
3833 clientMaxWindowBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "
"context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n"
, serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,
clientMaxWindowBits); } } while (0)
;
3834
3835 mNegotiatedExtensions = "permessage-deflate";
3836 } else {
3837 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE "
"compression object\n"); } } while (0)
3838 ("WebSocketChannel::OnTransportAvailable: Cannot init PMCE "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE "
"compression object\n"); } } while (0)
3839 "compression object\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE "
"compression object\n"); } } while (0)
;
3840 mPMCECompressor = nullptr;
3841 AbortSession(NS_ERROR_UNEXPECTED);
3842 return NS_ERROR_UNEXPECTED;
3843 }
3844 }
3845
3846 return CallStartWebsocketData();
3847 }
3848
3849 return NS_OK;
3850}
3851
3852NS_IMETHODIMPnsresult
3853WebSocketChannel::OnUpgradeFailed(nsresult aErrorCode) {
3854 // When socket process is enabled, this could be called on background thread.
3855
3856 LOG(("WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %" PRIx32 "]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %"
"x" "]", this, static_cast<uint32_t>(aErrorCode)); } }
while (0)
3857 static_cast<uint32_t>(aErrorCode)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %"
"x" "]", this, static_cast<uint32_t>(aErrorCode)); } }
while (0)
;
3858
3859 if (mStopped) {
3860 LOG(("WebSocketChannel::OnUpgradeFailed: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed: Already stopped"
); } } while (0)
;
3861 return NS_OK;
3862 }
3863
3864 MOZ_ASSERT(!mRecvdHttpUpgradeTransport, "OTA already called")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport"
" (" "OTA already called" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OTA already called" ")"); do { *((volatile int*)__null
) = 3864; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3865
3866 AbortSession(aErrorCode);
3867 return NS_OK;
3868}
3869
3870// nsIRequestObserver (from nsIStreamListener)
3871
3872NS_IMETHODIMPnsresult
3873WebSocketChannel::OnStartRequest(nsIRequest* aRequest) {
3874 LOG(("WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n"
, this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport
); } } while (0)
3875 this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n"
, this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport
); } } while (0)
;
3876 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3876; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3877 MOZ_ASSERT(!mGotUpgradeOK, "OTA duplicated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mGotUpgradeOK)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mGotUpgradeOK))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mGotUpgradeOK"
" (" "OTA duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 3877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mGotUpgradeOK"
") (" "OTA duplicated" ")"); do { *((volatile int*)__null) =
3877; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3878
3879 if (mStopped) {
3880 LOG(("WebSocketChannel::OnStartRequest: Channel Already Done\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Channel Already Done\n"
); } } while (0)
;
3881 AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED);
3882 return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED;
3883 }
3884
3885 nsresult rv;
3886 uint32_t status;
3887 char *val, *token;
3888
3889 rv = mHttpChannel->GetResponseStatus(&status);
3890 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3891 nsresult httpStatus;
3892 rv = NS_ERROR_WEBSOCKET_CONNECTION_REFUSED;
3893
3894 // If we failed to connect due to unsuccessful TLS handshake, we must
3895 // propagate a specific error to mozilla::dom::WebSocketImpl so it can set
3896 // status code to 1015. Otherwise return
3897 // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED.
3898 if (NS_SUCCEEDED(mHttpChannel->GetStatus(&httpStatus))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mHttpChannel->
GetStatus(&httpStatus))), 1)))
) {
3899 uint32_t errorClass;
3900 nsCOMPtr<nsINSSErrorsService> errSvc;
3901 errSvc = mozilla::components::NSSErrors::Service();
3902 // If GetErrorClass succeeds httpStatus is TLS related failure.
3903 if (errSvc &&
3904 NS_SUCCEEDED(errSvc->GetErrorClass(httpStatus, &errorClass))((bool)(__builtin_expect(!!(!NS_FAILED_impl(errSvc->GetErrorClass
(httpStatus, &errorClass))), 1)))
) {
3905 rv = NS_ERROR_NET_INADEQUATE_SECURITY;
3906 }
3907 }
3908
3909 LOG(("WebSocketChannel::OnStartRequest: No HTTP Response\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: No HTTP Response\n"
); } } while (0)
;
3910 AbortSession(rv);
3911 return rv;
3912 }
3913
3914 LOG(("WebSocketChannel::OnStartRequest: HTTP status %d\n", status))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: HTTP status %d\n"
, status); } } while (0)
;
3915 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
3916 do_QueryInterface(mHttpChannel);
3917 uint32_t versionMajor, versionMinor;
3918 rv = internalChannel->GetResponseVersion(&versionMajor, &versionMinor);
3919 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) ||
3920 !((versionMajor == 1 && versionMinor != 0) || versionMajor == 2) ||
3921 (versionMajor == 1 && status != 101) ||
3922 (versionMajor == 2 && status != 200)) {
3923 AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED);
3924 return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED;
3925 }
3926
3927 if (versionMajor == 1) {
3928 // These are only present on http/1.x websocket upgrades
3929 nsAutoCString respUpgrade;
3930 rv = mHttpChannel->GetResponseHeader("Upgrade"_ns, respUpgrade);
3931
3932 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3933 rv = NS_ERROR_ILLEGAL_VALUE;
3934 if (!respUpgrade.IsEmpty()) {
3935 val = respUpgrade.BeginWriting();
3936 while ((token = nsCRT::strtok(val, ", \t", &val))) {
3937 if (nsCRT::strcasecmp(token, "Websocket") == 0) {
3938 rv = NS_OK;
3939 break;
3940 }
3941 }
3942 }
3943 }
3944
3945 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3946 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header Upgrade: websocket not found\n"); } } while
(0)
3947 ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header Upgrade: websocket not found\n"); } } while
(0)
3948 "HTTP response header Upgrade: websocket not found\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header Upgrade: websocket not found\n"); } } while
(0)
;
3949 AbortSession(NS_ERROR_ILLEGAL_VALUE);
3950 return rv;
3951 }
3952
3953 nsAutoCString respConnection;
3954 rv = mHttpChannel->GetResponseHeader("Connection"_ns, respConnection);
3955
3956 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3957 rv = NS_ERROR_ILLEGAL_VALUE;
3958 if (!respConnection.IsEmpty()) {
3959 val = respConnection.BeginWriting();
3960 while ((token = nsCRT::strtok(val, ", \t", &val))) {
3961 if (nsCRT::strcasecmp(token, "Upgrade") == 0) {
3962 rv = NS_OK;
3963 break;
3964 }
3965 }
3966 }
3967 }
3968
3969 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3970 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header 'Connection: Upgrade' not found\n"); }
} while (0)
3971 ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header 'Connection: Upgrade' not found\n"); }
} while (0)
3972 "HTTP response header 'Connection: Upgrade' not found\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header 'Connection: Upgrade' not found\n"); }
} while (0)
;
3973 AbortSession(NS_ERROR_ILLEGAL_VALUE);
3974 return rv;
3975 }
3976
3977 nsAutoCString respAccept;
3978 rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Accept"_ns, respAccept);
3979
3980 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty() ||
3981 !respAccept.Equals(mHashedSecret)) {
3982 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header Sec-WebSocket-Accept check failed\n");
} } while (0)
3983 ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header Sec-WebSocket-Accept check failed\n");
} } while (0)
3984 "HTTP response header Sec-WebSocket-Accept check failed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: "
"HTTP response header Sec-WebSocket-Accept check failed\n");
} } while (0)
;
3985 LOG(("WebSocketChannel::OnStartRequest: Expected %s received %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Expected %s received %s\n"
, mHashedSecret.get(), respAccept.get()); } } while (0)
3986 mHashedSecret.get(), respAccept.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Expected %s received %s\n"
, mHashedSecret.get(), respAccept.get()); } } while (0)
;
3987#ifdef FUZZING
3988 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty()) {
3989#endif
3990 AbortSession(NS_ERROR_ILLEGAL_VALUE);
3991 return NS_ERROR_ILLEGAL_VALUE;
3992#ifdef FUZZING
3993 }
3994#endif
3995 }
3996 }
3997
3998 // If we sent a sub protocol header, verify the response matches.
3999 // If response contains protocol that was not in request, fail.
4000 // If response contained no protocol header, set to "" so the protocol
4001 // attribute of the WebSocket JS object reflects that
4002 if (!mProtocol.IsEmpty()) {
4003 nsAutoCString respProtocol;
4004 rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Protocol"_ns,
4005 respProtocol);
4006 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4007 rv = NS_ERROR_ILLEGAL_VALUE;
4008 val = mProtocol.BeginWriting();
4009 while ((token = nsCRT::strtok(val, ", \t", &val))) {
4010 if (strcmp(token, respProtocol.get()) == 0) {
4011 rv = NS_OK;
4012 break;
4013 }
4014 }
4015
4016 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4017 LOG(("WebsocketChannel::OnStartRequest: subprotocol %s confirmed",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: subprotocol %s confirmed"
, respProtocol.get()); } } while (0)
4018 respProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: subprotocol %s confirmed"
, respProtocol.get()); } } while (0)
;
4019 mProtocol = respProtocol;
4020 } else {
4021 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: "
"Server replied with non-matching subprotocol [%s]: aborting"
, respProtocol.get()); } } while (0)
4022 ("WebsocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: "
"Server replied with non-matching subprotocol [%s]: aborting"
, respProtocol.get()); } } while (0)
4023 "Server replied with non-matching subprotocol [%s]: aborting",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: "
"Server replied with non-matching subprotocol [%s]: aborting"
, respProtocol.get()); } } while (0)
4024 respProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: "
"Server replied with non-matching subprotocol [%s]: aborting"
, respProtocol.get()); } } while (0)
;
4025 mProtocol.Truncate();
4026 AbortSession(NS_ERROR_ILLEGAL_VALUE);
4027 return NS_ERROR_ILLEGAL_VALUE;
4028 }
4029 } else {
4030 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest "
"subprotocol [%s] not found - none returned", mProtocol.get(
)); } } while (0)
4031 ("WebsocketChannel::OnStartRequest "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest "
"subprotocol [%s] not found - none returned", mProtocol.get(
)); } } while (0)
4032 "subprotocol [%s] not found - none returned",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest "
"subprotocol [%s] not found - none returned", mProtocol.get(
)); } } while (0)
4033 mProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest "
"subprotocol [%s] not found - none returned", mProtocol.get(
)); } } while (0)
;
4034 mProtocol.Truncate();
4035 }
4036 }
4037
4038 rv = HandleExtensions();
4039 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4040
4041 // Update mEffectiveURL for off main thread URI access.
4042 nsCOMPtr<nsIURI> uri = mURI ? mURI : mOriginalURI;
4043 nsAutoCString spec;
4044 rv = uri->GetSpec(spec);
4045 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 4045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4045; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4046 CopyUTF8toUTF16(spec, mEffectiveURL);
4047
4048 mGotUpgradeOK = 1;
4049 if (mRecvdHttpUpgradeTransport) {
4050 // We're now done CONNECTING, which means we can now open another,
4051 // perhaps parallel, connection to the same host if one
4052 // is pending
4053 nsWSAdmissionManager::OnConnected(this);
4054
4055 return CallStartWebsocketData();
4056 }
4057
4058 return NS_OK;
4059}
4060
4061NS_IMETHODIMPnsresult
4062WebSocketChannel::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
4063 LOG(("WebSocketChannel::OnStopRequest() %p [%p %p %" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStopRequest() %p [%p %p %"
"x" "]\n", this, aRequest, mHttpChannel.get(), static_cast<
uint32_t>(aStatusCode)); } } while (0)
4064 aRequest, mHttpChannel.get(), static_cast<uint32_t>(aStatusCode)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStopRequest() %p [%p %p %"
"x" "]\n", this, aRequest, mHttpChannel.get(), static_cast<
uint32_t>(aStatusCode)); } } while (0)
;
4065 MOZ_ASSERT(NS_IsMainThread(), "not main thread")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()"
" (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 4065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
4065; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4066
4067 // OnTransportAvailable won't be called if the request is stopped with
4068 // an error. Abort the session now instead of waiting for timeout.
4069 if (NS_FAILED(aStatusCode)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatusCode)), 0))
)
&& !mRecvdHttpUpgradeTransport) {
4070 AbortSession(aStatusCode);
4071 }
4072
4073 ReportConnectionTelemetry(aStatusCode);
4074
4075 // This is the end of the HTTP upgrade transaction, the
4076 // upgraded streams live on
4077
4078 mChannel = nullptr;
4079 mHttpChannel = nullptr;
4080 mLoadGroup = nullptr;
4081 mCallbacks = nullptr;
4082
4083 return NS_OK;
4084}
4085
4086// nsIInputStreamCallback
4087
4088NS_IMETHODIMPnsresult
4089WebSocketChannel::OnInputStreamReady(nsIAsyncInputStream* aStream) {
4090 LOG(("WebSocketChannel::OnInputStreamReady() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady() %p\n"
, this); } } while (0)
;
4091 MOZ_DIAGNOSTIC_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 4091); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 4091; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4092
4093 if (!mSocketIn) { // did we we clean up the socket after scheduling
4094 // InputReady?
4095 return NS_OK;
4096 }
4097
4098 // this is after the http upgrade - so we are speaking websockets
4099 char buffer[2048];
4100 uint32_t count;
4101 nsresult rv;
4102
4103 do {
4104 rv = mSocketIn->Read((char*)buffer, sizeof(buffer), &count);
4105 LOG(("WebSocketChannel::OnInputStreamReady: read %u rv %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady: read %u rv %"
"x" "\n", count, static_cast<uint32_t>(rv)); } } while
(0)
4106 count, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady: read %u rv %"
"x" "\n", count, static_cast<uint32_t>(rv)); } } while
(0)
;
4107
4108 if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
4109 mSocketIn->AsyncWait(this, 0, 0, mIOThread);
4110 return NS_OK;
4111 }
4112
4113 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4114 AbortSession(rv);
4115 return rv;
4116 }
4117
4118 if (count == 0) {
4119 AbortSession(NS_BASE_STREAM_CLOSED);
4120 return NS_OK;
4121 }
4122
4123 if (mStopped) {
4124 continue;
4125 }
4126
4127 rv = ProcessInput((uint8_t*)buffer, count);
4128 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4129 AbortSession(rv);
4130 return rv;
4131 }
4132 } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mSocketIn);
4133
4134 return NS_OK;
4135}
4136
4137// nsIOutputStreamCallback
4138
4139NS_IMETHODIMPnsresult
4140WebSocketChannel::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
4141 LOG(("WebSocketChannel::OnOutputStreamReady() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady() %p\n"
, this); } } while (0)
;
4142 MOZ_DIAGNOSTIC_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 4142); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 4142; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4143 nsresult rv;
4144
4145 if (!mCurrentOut) PrimeNewOutgoingMessage();
4146
4147 while (mCurrentOut && mSocketOut) {
4148 const char* sndBuf;
4149 uint32_t toSend;
4150 uint32_t amtSent;
4151
4152 if (mHdrOut) {
4153 sndBuf = (const char*)mHdrOut;
4154 toSend = mHdrOutToSend;
4155 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: "
"Try to send %u of hdr/copybreak\n", toSend); } } while (0)
4156 ("WebSocketChannel::OnOutputStreamReady: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: "
"Try to send %u of hdr/copybreak\n", toSend); } } while (0)
4157 "Try to send %u of hdr/copybreak\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: "
"Try to send %u of hdr/copybreak\n", toSend); } } while (0)
4158 toSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: "
"Try to send %u of hdr/copybreak\n", toSend); } } while (0)
;
4159 } else {
4160 sndBuf = (char*)mCurrentOut->BeginReading() + mCurrentOutSent;
4161 toSend = mCurrentOut->Length() - mCurrentOutSent;
4162 if (toSend > 0) {
4163 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: "
"Try to send %u of data\n", this, toSend); } } while (0)
4164 ("WebSocketChannel::OnOutputStreamReady [%p]: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: "
"Try to send %u of data\n", this, toSend); } } while (0)
4165 "Try to send %u of data\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: "
"Try to send %u of data\n", this, toSend); } } while (0)
4166 this, toSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: "
"Try to send %u of data\n", this, toSend); } } while (0)
;
4167 }
4168 }
4169
4170 if (toSend == 0) {
4171 amtSent = 0;
4172 } else {
4173 rv = mSocketOut->Write(sndBuf, toSend, &amtSent);
4174 LOG(("WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %"
"x" "\n", this, amtSent, static_cast<uint32_t>(rv)); }
} while (0)
4175 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %"
"x" "\n", this, amtSent, static_cast<uint32_t>(rv)); }
} while (0)
4176 this, amtSent, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %"
"x" "\n", this, amtSent, static_cast<uint32_t>(rv)); }
} while (0)
;
4177
4178 if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
4179 mSocketOut->AsyncWait(this, 0, 0, mIOThread);
4180 return NS_OK;
4181 }
4182
4183 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4184 AbortSession(rv);
4185 return NS_OK;
4186 }
4187 }
4188
4189 if (mHdrOut) {
4190 if (amtSent == toSend) {
4191 mHdrOut = nullptr;
4192 mHdrOutToSend = 0;
4193 } else {
4194 mHdrOut += amtSent;
4195 mHdrOutToSend -= amtSent;
4196 mSocketOut->AsyncWait(this, 0, 0, mIOThread);
4197 }
4198 } else {
4199 if (amtSent == toSend) {
4200 if (!mStopped) {
4201 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
4202 target->Dispatch(
4203 new CallAcknowledge(this, mCurrentOut->OrigLength()),
4204 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
4205 } else {
4206 return NS_ERROR_UNEXPECTED;
4207 }
4208 }
4209 DeleteCurrentOutGoingMessage();
4210 PrimeNewOutgoingMessage();
4211 } else {
4212 mCurrentOutSent += amtSent;
4213 mSocketOut->AsyncWait(this, 0, 0, mIOThread);
4214 }
4215 }
4216 }
4217
4218 if (mReleaseOnTransmit) ReleaseSession();
4219 return NS_OK;
4220}
4221
4222// nsIStreamListener
4223
4224NS_IMETHODIMPnsresult
4225WebSocketChannel::OnDataAvailable(nsIRequest* aRequest,
4226 nsIInputStream* aInputStream,
4227 uint64_t aOffset, uint32_t aCount) {
4228 LOG(("WebSocketChannel::OnDataAvailable() %p [%p %p %p %" PRIu64 " %u]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable() %p [%p %p %p %"
"l" "u" " %u]\n", this, aRequest, mHttpChannel.get(), aInputStream
, aOffset, aCount); } } while (0)
4229 this, aRequest, mHttpChannel.get(), aInputStream, aOffset, aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable() %p [%p %p %p %"
"l" "u" " %u]\n", this, aRequest, mHttpChannel.get(), aInputStream
, aOffset, aCount); } } while (0)
;
4230
4231 // This is the HTTP OnDataAvailable Method, which means this is http data in
4232 // response to the upgrade request and there should be no http response body
4233 // if the upgrade succeeded. This generally should be caught by a non 101
4234 // response code in OnStartRequest().. so we can ignore the data here
4235
4236 LOG(("WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n"
, aCount); } } while (0)
4237 aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n"
, aCount); } } while (0)
;
4238
4239 return NS_OK;
4240}
4241
4242void WebSocketChannel::DoEnqueueOutgoingMessage() {
4243 LOG(("WebSocketChannel::DoEnqueueOutgoingMessage() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage() %p\n"
, this); } } while (0)
;
4244 MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mIOThread->IsOnCurrentThread()" " (" "not on right thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp"
, 4244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 4244; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4245
4246 if (!mCurrentOut) {
4247 PrimeNewOutgoingMessage();
4248 }
4249
4250 while (mCurrentOut && mConnection) {
4251 nsresult rv = NS_OK;
4252 if (mCurrentOut->Length() - mCurrentOutSent == 0) {
4253 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while
(0)
4254 ("WebSocketChannel::DoEnqueueOutgoingMessage: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while
(0)
4255 "Try to send %u of hdr/copybreak\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while
(0)
4256 mHdrOutToSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while
(0)
;
4257 rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, nullptr, 0);
4258 } else {
4259 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut
->Length()); } } while (0)
4260 ("WebSocketChannel::DoEnqueueOutgoingMessage: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut
->Length()); } } while (0)
4261 "Try to send %u of hdr and %u of data\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut
->Length()); } } while (0)
4262 mHdrOutToSend, mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: "
"Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut
->Length()); } } while (0)
;
4263 rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend,
4264 (uint8_t*)mCurrentOut->BeginReading(),
4265 mCurrentOut->Length());
4266 }
4267
4268 LOG(("WebSocketChannel::DoEnqueueOutgoingMessage: rv %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: rv %"
"x" "\n", static_cast<uint32_t>(rv)); } } while (0)
4269 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: rv %"
"x" "\n", static_cast<uint32_t>(rv)); } } while (0)
;
4270 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4271 AbortSession(rv);
4272 return;
4273 }
4274
4275 if (!mStopped) {
4276 // TODO: Currently, we assume that data is completely written to the
4277 // socket after sending it to socket process, but it's not true. The data
4278 // could be queued in socket process and waiting for the socket to be able
4279 // to write. We should implement flow control for this in bug 1726552.
4280 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
4281 target->Dispatch(new CallAcknowledge(this, mCurrentOut->OrigLength()),
4282 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
4283 } else {
4284 AbortSession(NS_ERROR_UNEXPECTED);
4285 return;
4286 }
4287 }
4288 DeleteCurrentOutGoingMessage();
4289 PrimeNewOutgoingMessage();
4290 }
4291
4292 if (mReleaseOnTransmit) {
4293 ReleaseSession();
4294 }
4295}
4296
4297void WebSocketChannel::OnError(nsresult aStatus) { AbortSession(aStatus); }
4298
4299void WebSocketChannel::OnTCPClosed() { mTCPClosed = true; }
4300
4301nsresult WebSocketChannel::OnDataReceived(uint8_t* aData, uint32_t aCount) {
4302 return ProcessInput(aData, aCount);
4303}
4304
4305} // namespace mozilla::net
4306
4307#undef CLOSE_GOING_AWAY