Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp
Warning:line 2677, 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-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/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-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_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 "nsAlgorithm.h"
28#include "nsCRT.h"
29#include "nsCharSeparatedTokenizer.h"
30#include "nsComponentManagerUtils.h"
31#include "nsError.h"
32#include "nsIAsyncVerifyRedirectCallback.h"
33#include "nsICancelable.h"
34#include "nsIChannel.h"
35#include "nsIClassOfService.h"
36#include "nsICryptoHash.h"
37#include "nsIDNSRecord.h"
38#include "nsIDNSService.h"
39#include "nsIDashboardEventNotifier.h"
40#include "nsIEventTarget.h"
41#include "nsIHttpChannel.h"
42#include "nsIIOService.h"
43#include "nsINSSErrorsService.h"
44#include "nsINetworkLinkService.h"
45#include "nsINode.h"
46#include "nsIObserverService.h"
47#include "nsIPrefBranch.h"
48#include "nsIProtocolHandler.h"
49#include "nsIProtocolProxyService.h"
50#include "nsIProxiedChannel.h"
51#include "nsIProxyInfo.h"
52#include "nsIRandomGenerator.h"
53#include "nsIRunnable.h"
54#include "nsISocketTransport.h"
55#include "nsITLSSocketControl.h"
56#include "nsITransportProvider.h"
57#include "nsITransportSecurityInfo.h"
58#include "nsIURI.h"
59#include "nsIURIMutator.h"
60#include "nsNetCID.h"
61#include "nsNetUtil.h"
62#include "nsProxyRelease.h"
63#include "nsServiceManagerUtils.h"
64#include "nsSocketTransportService2.h"
65#include "nsStringStream.h"
66#include "nsThreadUtils.h"
67#include "plbase64.h"
68#include "prmem.h"
69#include "prnetdb.h"
70#include "zlib.h"
71
72// rather than slurp up all of nsIWebSocket.idl, which lives outside necko, just
73// dupe one constant we need from it
74#define CLOSE_GOING_AWAY 1001
75
76using namespace mozilla;
77using namespace mozilla::net;
78
79namespace mozilla::net {
80
81NS_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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 86
; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); 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((sizeof(table) / sizeof
(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
82 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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 86
; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); 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((sizeof(table) / sizeof
(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
83 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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 86
; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); 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((sizeof(table) / sizeof
(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
84 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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 86
; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); 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((sizeof(table) / sizeof
(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
85 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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 86
; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); 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((sizeof(table) / sizeof
(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
86 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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 86
; __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"
, 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 86; __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"
, 86); 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((sizeof(table) / sizeof
(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
87
88// We implement RFC 6455, which uses Sec-WebSocket-Version: 13 on the wire.
89#define SEC_WEBSOCKET_VERSION"13" "13"
90
91/*
92 * About SSL unsigned certificates
93 *
94 * wss will not work to a host using an unsigned certificate unless there
95 * is already an exception (i.e. it cannot popup a dialog asking for
96 * a security exception). This is similar to how an inlined img will
97 * fail without a dialog if fails for the same reason. This should not
98 * be a problem in practice as it is expected the websocket javascript
99 * is served from the same host as the websocket server (or of course,
100 * a valid cert could just be provided).
101 *
102 */
103
104// some helper classes
105
106//-----------------------------------------------------------------------------
107// FailDelayManager
108//
109// Stores entries (searchable by {host, port}) of connections that have recently
110// failed, so we can do delay of reconnects per RFC 6455 Section 7.2.3
111//-----------------------------------------------------------------------------
112
113// Initial reconnect delay is randomly chosen between 200-400 ms.
114// This is a gentler backoff than the 0-5 seconds the spec offhandedly suggests.
115const uint32_t kWSReconnectInitialBaseDelay = 200;
116const uint32_t kWSReconnectInitialRandomDelay = 200;
117
118// Base lifetime (in ms) of a FailDelay: kept longer if more failures occur
119const uint32_t kWSReconnectBaseLifeTime = 60 * 1000;
120// Maximum reconnect delay (in ms)
121const uint32_t kWSReconnectMaxDelay = 60 * 1000;
122
123// hold record of failed connections, and calculates needed delay for reconnects
124// to same host/path/port.
125class FailDelay {
126 public:
127 FailDelay(nsCString address, nsCString path, int32_t port)
128 : mAddress(std::move(address)), mPath(std::move(path)), mPort(port) {
129 mLastFailure = TimeStamp::Now();
130 mNextDelay = kWSReconnectInitialBaseDelay +
131 (rand() % kWSReconnectInitialRandomDelay);
132 }
133
134 // Called to update settings when connection fails again.
135 void FailedAgain() {
136 mLastFailure = TimeStamp::Now();
137 // We use a truncated exponential backoff as suggested by RFC 6455,
138 // but multiply by 1.5 instead of 2 to be more gradual.
139 mNextDelay = static_cast<uint32_t>(
140 std::min<double>(kWSReconnectMaxDelay, mNextDelay * 1.5));
141 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)
142 ("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)
143 "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)
144 "%" 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)
145 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)
;
146 }
147
148 // returns 0 if there is no need to delay (i.e. delay interval is over)
149 uint32_t RemainingDelay(TimeStamp rightNow) {
150 TimeDuration dur = rightNow - mLastFailure;
151 uint32_t sinceFail = (uint32_t)dur.ToMilliseconds();
152 if (sinceFail > mNextDelay) return 0;
153
154 return mNextDelay - sinceFail;
155 }
156
157 bool IsExpired(TimeStamp rightNow) {
158 return (mLastFailure + TimeDuration::FromMilliseconds(
159 kWSReconnectBaseLifeTime + mNextDelay)) <=
160 rightNow;
161 }
162
163 nsCString mAddress; // IP address (or hostname if using proxy)
164 nsCString mPath;
165 int32_t mPort;
166
167 private:
168 TimeStamp mLastFailure; // Time of last failed attempt
169 // mLastFailure + mNextDelay is the soonest we'll allow a reconnect
170 uint32_t mNextDelay; // milliseconds
171};
172
173class FailDelayManager {
174 public:
175 FailDelayManager() {
176 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)
;
177
178 mDelaysDisabled = false;
179
180 nsCOMPtr<nsIPrefBranch> prefService;
181 prefService = mozilla::components::Preferences::Service();
182 if (!prefService) {
183 return;
184 }
185 bool boolpref = true;
186 nsresult rv;
187 rv = prefService->GetBoolPref("network.websocket.delay-failed-reconnects",
188 &boolpref);
189 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !boolpref) {
190 mDelaysDisabled = true;
191 }
192 }
193
194 ~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)
; }
195
196 void Add(nsCString& address, nsCString& path, int32_t port) {
197 if (mDelaysDisabled) return;
198
199 UniquePtr<FailDelay> record(new FailDelay(address, path, port));
200 mEntries.AppendElement(std::move(record));
201 }
202
203 // Element returned may not be valid after next main thread event: don't keep
204 // pointer to it around
205 FailDelay* Lookup(nsCString& address, nsCString& path, int32_t port,
206 uint32_t* outIndex = nullptr) {
207 if (mDelaysDisabled) return nullptr;
208
209 FailDelay* result = nullptr;
210 TimeStamp rightNow = TimeStamp::Now();
211
212 // We also remove expired entries during search: iterate from end to make
213 // indexing simpler
214 for (int32_t i = mEntries.Length() - 1; i >= 0; --i) {
215 FailDelay* fail = mEntries[i].get();
216 if (fail->mAddress.Equals(address) && fail->mPath.Equals(path) &&
217 fail->mPort == port) {
218 if (outIndex) *outIndex = i;
219 result = fail;
220 // break here: removing more entries would mess up *outIndex.
221 // Any remaining expired entries will be deleted next time Lookup
222 // finds nothing, which is the most common case anyway.
223 break;
224 }
225 if (fail->IsExpired(rightNow)) {
226 mEntries.RemoveElementAt(i);
227 }
228 }
229 return result;
230 }
231
232 // returns true if channel connects immediately, or false if it's delayed
233 void DelayOrBegin(WebSocketChannel* ws) {
234 if (!mDelaysDisabled) {
235 uint32_t failIndex = 0;
236 FailDelay* fail = Lookup(ws->mAddress, ws->mPath, ws->mPort, &failIndex);
237
238 if (fail) {
239 TimeStamp rightNow = TimeStamp::Now();
240
241 uint32_t remainingDelay = fail->RemainingDelay(rightNow);
242 if (remainingDelay) {
243 // reconnecting within delay interval: delay by remaining time
244 nsresult rv;
245 MutexAutoLock lock(ws->mMutex);
246 rv = NS_NewTimerWithCallback(getter_AddRefs(ws->mReconnectDelayTimer),
247 ws, remainingDelay,
248 nsITimer::TYPE_ONE_SHOT);
249 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
250 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)
251 ("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)
252 " 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)
253 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)
;
254 ws->mConnecting = CONNECTING_DELAYED;
255 return;
256 }
257 // if timer fails (which is very unlikely), drop down to BeginOpen
258 // call
259 } else if (fail->IsExpired(rightNow)) {
260 mEntries.RemoveElementAt(failIndex);
261 }
262 }
263 }
264
265 // Delays disabled, or no previous failure, or we're reconnecting after
266 // scheduled delay interval has passed: connect.
267 ws->BeginOpen(true);
268 }
269
270 // Remove() also deletes all expired entries as it iterates: better for
271 // battery life than using a periodic timer.
272 void Remove(nsCString& address, nsCString& path, int32_t port) {
273 TimeStamp rightNow = TimeStamp::Now();
274
275 // iterate from end, to make deletion indexing easier
276 for (int32_t i = mEntries.Length() - 1; i >= 0; --i) {
277 FailDelay* entry = mEntries[i].get();
278 if ((entry->mAddress.Equals(address) && entry->mPath.Equals(path) &&
279 entry->mPort == port) ||
280 entry->IsExpired(rightNow)) {
281 mEntries.RemoveElementAt(i);
282 }
283 }
284 }
285
286 private:
287 nsTArray<UniquePtr<FailDelay>> mEntries;
288 bool mDelaysDisabled;
289};
290
291//-----------------------------------------------------------------------------
292// nsWSAdmissionManager
293//
294// 1) Ensures that only one websocket at a time is CONNECTING to a given IP
295// address (or hostname, if using proxy), per RFC 6455 Section 4.1.
296// 2) Delays reconnects to IP/host after connection failure, per Section 7.2.3
297//-----------------------------------------------------------------------------
298
299class nsWSAdmissionManager {
300 public:
301 static void Init() {
302 StaticMutexAutoLock lock(sLock);
303 if (!sManager) {
304 sManager = new nsWSAdmissionManager();
305 }
306 }
307
308 static void Shutdown() {
309 StaticMutexAutoLock lock(sLock);
310 delete sManager;
311 sManager = nullptr;
312 }
313
314 // Determine if we will open connection immediately (returns true), or
315 // delay/queue the connection (returns false)
316 static void ConditionallyConnect(WebSocketChannel* ws) {
317 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)
;
318 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"
, 318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
318; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
319 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"
, 319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ws->mConnecting == NOT_CONNECTING"
") (" "opening state" ")"); do { *((volatile int*)__null) = 319
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
320
321 StaticMutexAutoLock lock(sLock);
322 if (!sManager) {
323 return;
324 }
325
326 // If there is already another WS channel connecting to this IP address,
327 // defer BeginOpen and mark as waiting in queue.
328 bool hostFound = (sManager->IndexOf(ws->mAddress, ws->mOriginSuffix) >= 0);
329
330 uint32_t failIndex = 0;
331 FailDelay* fail = sManager->mFailures.Lookup(ws->mAddress, ws->mPath,
332 ws->mPort, &failIndex);
333 bool existingFail = fail != nullptr;
334
335 // Always add ourselves to queue, even if we'll connect immediately
336 UniquePtr<nsOpenConn> newdata(
337 new nsOpenConn(ws->mAddress, ws->mOriginSuffix, existingFail, ws));
338
339 // If a connection has not previously failed then prioritize it over
340 // connections that have
341 if (existingFail) {
342 sManager->mQueue.AppendElement(std::move(newdata));
343 } else {
344 uint32_t insertionIndex = sManager->IndexOfFirstFailure();
345 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"
, 346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()"
") (" "Insertion index outside bounds" ")"); do { *((volatile
int*)__null) = 346; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
346 "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"
, 346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()"
") (" "Insertion index outside bounds" ")"); do { *((volatile
int*)__null) = 346; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
347 sManager->mQueue.InsertElementAt(insertionIndex, std::move(newdata));
348 }
349
350 if (hostFound) {
351 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)
352 ("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)
353 "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)
;
354 ws->mConnecting = CONNECTING_QUEUED;
355 } else {
356 sManager->mFailures.DelayOrBegin(ws);
357 }
358 }
359
360 static void OnConnected(WebSocketChannel* aChannel) {
361 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)
;
362
363 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"
, 363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
363; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
364 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"
, 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS"
") (" "Channel completed connect, but not connecting?" ")");
do { *((volatile int*)__null) = 365; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
365 "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"
, 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS"
") (" "Channel completed connect, but not connecting?" ")");
do { *((volatile int*)__null) = 365; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
366
367 StaticMutexAutoLock lock(sLock);
368 if (!sManager) {
369 return;
370 }
371
372 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)
;
373 aChannel->mConnecting = NOT_CONNECTING;
374
375 // Remove from queue
376 sManager->RemoveFromQueue(aChannel);
377
378 // Connection succeeded, so stop keeping track of any previous failures
379 sManager->mFailures.Remove(aChannel->mAddress, aChannel->mPath,
380 aChannel->mPort);
381
382 // Check for queued connections to same host.
383 // Note: still need to check for failures, since next websocket with same
384 // host may have different port
385 sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix);
386 }
387
388 // Called every time a websocket channel ends its session (including going
389 // away w/o ever successfully creating a connection)
390 static void OnStopSession(WebSocketChannel* aChannel, nsresult aReason) {
391 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)
392 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)
;
393
394 StaticMutexAutoLock lock(sLock);
395 if (!sManager) {
396 return;
397 }
398
399 if (NS_FAILED(aReason)((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0)))) {
400 // Have we seen this failure before?
401 FailDelay* knownFailure = sManager->mFailures.Lookup(
402 aChannel->mAddress, aChannel->mPath, aChannel->mPort);
403 if (knownFailure) {
404 if (aReason == NS_ERROR_NOT_CONNECTED) {
405 // Don't count close() before connection as a network error
406 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)
407 ("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)
408 " [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)
409 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)
410 (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)
;
411 } else {
412 // repeated failure to connect: increase delay for next connection
413 knownFailure->FailedAgain();
414 }
415 } else {
416 // new connection failure: record it.
417 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)
418 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)
419 (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)
;
420 sManager->mFailures.Add(aChannel->mAddress, aChannel->mPath,
421 aChannel->mPort);
422 }
423 }
424
425 if (NS_IsMainThread()) {
426 ContinueOnStopSession(aChannel, aReason);
427 } else {
428 NS_DispatchToMainThread(NS_NewRunnableFunction(
429 "nsWSAdmissionManager::ContinueOnStopSession",
430 [channel = RefPtr{aChannel}, reason = aReason]() {
431 StaticMutexAutoLock lock(sLock);
432 if (!sManager) {
433 return;
434 }
435
436 nsWSAdmissionManager::ContinueOnStopSession(channel, reason);
437 }));
438 }
439 }
440
441 static void ContinueOnStopSession(WebSocketChannel* aChannel,
442 nsresult aReason) {
443 sLock.AssertCurrentThreadOwns();
444 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"
, 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
444; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
445
446 if (!aChannel->mConnecting) {
447 return;
448 }
449
450 // Only way a connecting channel may get here w/o failing is if it
451 // was closed with GOING_AWAY (1001) because of navigation, tab
452 // close, etc.
453#ifdef DEBUG1
454 {
455 MutexAutoLock lock(aChannel->mMutex);
456 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"
, 458); 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) = 458; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
457 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"
, 458); 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) = 458; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
458 "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"
, 458); 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) = 458; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
459 }
460#endif
461 Unused << aReason;
462
463 sManager->RemoveFromQueue(aChannel);
464
465 bool wasNotQueued = (aChannel->mConnecting != CONNECTING_QUEUED);
466 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)
;
467 aChannel->mConnecting = NOT_CONNECTING;
468 if (wasNotQueued) {
469 sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix);
470 }
471 }
472
473 static void IncrementSessionCount() {
474 StaticMutexAutoLock lock(sLock);
475 if (!sManager) {
476 return;
477 }
478 sManager->mSessionCount++;
479 }
480
481 static void DecrementSessionCount() {
482 StaticMutexAutoLock lock(sLock);
483 if (!sManager) {
484 return;
485 }
486 sManager->mSessionCount--;
487 }
488
489 static void GetSessionCount(int32_t& aSessionCount) {
490 StaticMutexAutoLock lock(sLock);
491 if (!sManager) {
492 return;
493 }
494 aSessionCount = sManager->mSessionCount;
495 }
496
497 private:
498 nsWSAdmissionManager() : mSessionCount(0) {
499 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)
;
500 }
501
502 ~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)
; }
503
504 class nsOpenConn {
505 public:
506 nsOpenConn(nsCString& addr, nsCString& originSuffix, bool failed,
507 WebSocketChannel* channel)
508 : mAddress(addr),
509 mOriginSuffix(originSuffix),
510 mFailed(failed),
511 mChannel(channel) {
512 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)
;
513 }
514 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); }
515
516 nsCString mAddress;
517 nsCString mOriginSuffix;
518 bool mFailed = false;
519 RefPtr<WebSocketChannel> mChannel;
520 };
521
522 void ConnectNext(nsCString& hostName, nsCString& originSuffix) {
523 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"
, 523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
523; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
524
525 int32_t index = IndexOf(hostName, originSuffix);
526 if (index >= 0) {
527 WebSocketChannel* chan = mQueue[index]->mChannel;
528
529 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"
, 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED"
") (" "transaction not queued but in queue" ")"); do { *((volatile
int*)__null) = 530; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
530 "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"
, 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED"
") (" "transaction not queued but in queue" ")"); do { *((volatile
int*)__null) = 530; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
531 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)
;
532
533 mFailures.DelayOrBegin(chan);
534 }
535 }
536
537 void RemoveFromQueue(WebSocketChannel* aChannel) {
538 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)
;
539 int32_t index = IndexOf(aChannel);
540 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"
, 540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index >= 0"
") (" "connection to remove not in queue" ")"); do { *((volatile
int*)__null) = 540; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
541 if (index >= 0) {
542 mQueue.RemoveElementAt(index);
543 }
544 }
545
546 int32_t IndexOf(nsCString& aAddress, nsCString& aOriginSuffix) {
547 for (uint32_t i = 0; i < mQueue.Length(); i++) {
548 bool isPartitioned = StaticPrefs::privacy_partition_network_state() ||
549 StaticPrefs::privacy_firstparty_isolate();
550 if (aAddress == (mQueue[i])->mAddress &&
551 (!isPartitioned || aOriginSuffix == (mQueue[i])->mOriginSuffix)) {
552 return i;
553 }
554 }
555 return -1;
556 }
557
558 int32_t IndexOf(WebSocketChannel* aChannel) {
559 for (uint32_t i = 0; i < mQueue.Length(); i++) {
560 if (aChannel == (mQueue[i])->mChannel) return i;
561 }
562 return -1;
563 }
564
565 // Returns the index of the first entry that failed, or else the last entry if
566 // none found
567 uint32_t IndexOfFirstFailure() {
568 for (uint32_t i = 0; i < mQueue.Length(); i++) {
569 if (mQueue[i]->mFailed) return i;
570 }
571 return mQueue.Length();
572 }
573
574 // SessionCount might be decremented from the main or the socket
575 // thread, so manage it with atomic counters
576 Atomic<int32_t> mSessionCount;
577
578 // Queue for websockets that have not completed connecting yet.
579 // The first nsOpenConn with a given address will be either be
580 // CONNECTING_IN_PROGRESS or CONNECTING_DELAYED. Later ones with the same
581 // hostname must be CONNECTING_QUEUED.
582 //
583 // We could hash hostnames instead of using a single big vector here, but the
584 // dataset is expected to be small.
585 nsTArray<UniquePtr<nsOpenConn>> mQueue;
586
587 FailDelayManager mFailures;
588
589 static nsWSAdmissionManager* sManager MOZ_GUARDED_BY(sLock)__attribute__((guarded_by(sLock)));
590 static StaticMutex sLock;
591};
592
593nsWSAdmissionManager* nsWSAdmissionManager::sManager;
594StaticMutex nsWSAdmissionManager::sLock;
595
596//-----------------------------------------------------------------------------
597// CallOnMessageAvailable
598//-----------------------------------------------------------------------------
599
600class CallOnMessageAvailable final : public Runnable {
601 public:
602 CallOnMessageAvailable(WebSocketChannel* aChannel, nsACString& aData,
603 int32_t aLen)
604 : Runnable("net::CallOnMessageAvailable"),
605 mChannel(aChannel),
606 mListenerMT(aChannel->mListenerMT),
607 mData(aData),
608 mLen(aLen) {}
609
610 NS_IMETHODvirtual nsresult Run() override {
611 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"
, 611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 611; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
612
613 if (mListenerMT) {
614 nsresult rv;
615 if (mLen < 0) {
616 rv = mListenerMT->mListener->OnMessageAvailable(mListenerMT->mContext,
617 mData);
618 } else {
619 rv = mListenerMT->mListener->OnBinaryMessageAvailable(
620 mListenerMT->mContext, mData);
621 }
622 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
623 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)
624 ("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)
625 "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)
626 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)
;
627 }
628 }
629
630 return NS_OK;
631 }
632
633 private:
634 ~CallOnMessageAvailable() = default;
635
636 RefPtr<WebSocketChannel> mChannel;
637 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
638 nsCString mData;
639 int32_t mLen;
640};
641
642//-----------------------------------------------------------------------------
643// CallOnStop
644//-----------------------------------------------------------------------------
645
646class CallOnStop final : public Runnable {
647 public:
648 CallOnStop(WebSocketChannel* aChannel, nsresult aReason)
649 : Runnable("net::CallOnStop"),
650 mChannel(aChannel),
651 mListenerMT(mChannel->mListenerMT),
652 mReason(aReason) {}
653
654 NS_IMETHODvirtual nsresult Run() override {
655 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"
, 655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 655; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
656
657 if (mListenerMT) {
658 nsresult rv =
659 mListenerMT->mListener->OnStop(mListenerMT->mContext, mReason);
660 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
661 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)
662 ("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)
663 "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)
664 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)
;
665 }
666 mChannel->mListenerMT = nullptr;
667 }
668
669 return NS_OK;
670 }
671
672 private:
673 ~CallOnStop() = default;
674
675 RefPtr<WebSocketChannel> mChannel;
676 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
677 nsresult mReason;
678};
679
680//-----------------------------------------------------------------------------
681// CallOnServerClose
682//-----------------------------------------------------------------------------
683
684class CallOnServerClose final : public Runnable {
685 public:
686 CallOnServerClose(WebSocketChannel* aChannel, uint16_t aCode,
687 nsACString& aReason)
688 : Runnable("net::CallOnServerClose"),
689 mChannel(aChannel),
690 mListenerMT(mChannel->mListenerMT),
691 mCode(aCode),
692 mReason(aReason) {}
693
694 NS_IMETHODvirtual nsresult Run() override {
695 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"
, 695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 695; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
696
697 if (mListenerMT) {
698 nsresult rv = mListenerMT->mListener->OnServerClose(mListenerMT->mContext,
699 mCode, mReason);
700 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
701 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)
702 ("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)
703 "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)
704 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)
;
705 }
706 }
707 return NS_OK;
708 }
709
710 private:
711 ~CallOnServerClose() = default;
712
713 RefPtr<WebSocketChannel> mChannel;
714 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
715 uint16_t mCode;
716 nsCString mReason;
717};
718
719//-----------------------------------------------------------------------------
720// CallAcknowledge
721//-----------------------------------------------------------------------------
722
723class CallAcknowledge final : public Runnable {
724 public:
725 CallAcknowledge(WebSocketChannel* aChannel, uint32_t aSize)
726 : Runnable("net::CallAcknowledge"),
727 mChannel(aChannel),
728 mListenerMT(mChannel->mListenerMT),
729 mSize(aSize) {}
730
731 NS_IMETHODvirtual nsresult Run() override {
732 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"
, 732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()"
")"); do { *((volatile int*)__null) = 732; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
733
734 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)
;
735 if (mListenerMT) {
736 nsresult rv =
737 mListenerMT->mListener->OnAcknowledge(mListenerMT->mContext, mSize);
738 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
739 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)
740 ")\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)
741 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)
;
742 }
743 }
744 return NS_OK;
745 }
746
747 private:
748 ~CallAcknowledge() = default;
749
750 RefPtr<WebSocketChannel> mChannel;
751 RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT;
752 uint32_t mSize;
753};
754
755//-----------------------------------------------------------------------------
756// CallOnTransportAvailable
757//-----------------------------------------------------------------------------
758
759class CallOnTransportAvailable final : public Runnable {
760 public:
761 CallOnTransportAvailable(WebSocketChannel* aChannel,
762 nsISocketTransport* aTransport,
763 nsIAsyncInputStream* aSocketIn,
764 nsIAsyncOutputStream* aSocketOut)
765 : Runnable("net::CallOnTransportAvailble"),
766 mChannel(aChannel),
767 mTransport(aTransport),
768 mSocketIn(aSocketIn),
769 mSocketOut(aSocketOut) {}
770
771 NS_IMETHODvirtual nsresult Run() override {
772 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)
;
773 return mChannel->OnTransportAvailable(mTransport, mSocketIn, mSocketOut);
774 }
775
776 private:
777 ~CallOnTransportAvailable() = default;
778
779 RefPtr<WebSocketChannel> mChannel;
780 nsCOMPtr<nsISocketTransport> mTransport;
781 nsCOMPtr<nsIAsyncInputStream> mSocketIn;
782 nsCOMPtr<nsIAsyncOutputStream> mSocketOut;
783};
784
785//-----------------------------------------------------------------------------
786// PMCECompression
787//-----------------------------------------------------------------------------
788
789class PMCECompression {
790 public:
791 PMCECompression(bool aNoContextTakeover, int32_t aLocalMaxWindowBits,
792 int32_t aRemoteMaxWindowBits)
793 : mActive(false),
794 mNoContextTakeover(aNoContextTakeover),
795 mResetDeflater(false),
796 mMessageDeflated(false) {
797 this->mDeflater.next_in = nullptr;
798 this->mDeflater.avail_in = 0;
799 this->mDeflater.total_in = 0;
800 this->mDeflater.next_out = nullptr;
801 this->mDeflater.avail_out = 0;
802 this->mDeflater.total_out = 0;
803 this->mDeflater.msg = nullptr;
804 this->mDeflater.state = nullptr;
805 this->mDeflater.data_type = 0;
806 this->mDeflater.adler = 0;
807 this->mDeflater.reserved = 0;
808 this->mInflater.next_in = nullptr;
809 this->mInflater.avail_in = 0;
810 this->mInflater.total_in = 0;
811 this->mInflater.next_out = nullptr;
812 this->mInflater.avail_out = 0;
813 this->mInflater.total_out = 0;
814 this->mInflater.msg = nullptr;
815 this->mInflater.state = nullptr;
816 this->mInflater.data_type = 0;
817 this->mInflater.adler = 0;
818 this->mInflater.reserved = 0;
819 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)
;
820
821 mDeflater.zalloc = mInflater.zalloc = Z_NULL0;
822 mDeflater.zfree = mInflater.zfree = Z_NULL0;
823 mDeflater.opaque = mInflater.opaque = Z_NULL0;
824
825 if (deflateInit2(&mDeflater, Z_DEFAULT_COMPRESSION, Z_DEFLATED,MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits
),(8), (0), "1.3.1", (int)sizeof(z_stream))
826 -aLocalMaxWindowBits, 8, Z_DEFAULT_STRATEGY)MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits
),(8), (0), "1.3.1", (int)sizeof(z_stream))
== Z_OK0) {
827 if (inflateInit2(&mInflater, -aRemoteMaxWindowBits)MOZ_Z_inflateInit2_((&mInflater), (-aRemoteMaxWindowBits)
, "1.3.1", (int)sizeof(z_stream))
== Z_OK0) {
828 mActive = true;
829 } else {
830 deflateEndMOZ_Z_deflateEnd(&mDeflater);
831 }
832 }
833 }
834
835 ~PMCECompression() {
836 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)
;
837
838 if (mActive) {
839 inflateEndMOZ_Z_inflateEnd(&mInflater);
840 deflateEndMOZ_Z_deflateEnd(&mDeflater);
841 }
842 }
843
844 bool Active() { return mActive; }
845
846 void SetMessageDeflated() {
847 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"
, 847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mMessageDeflated"
")"); do { *((volatile int*)__null) = 847; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
848 mMessageDeflated = true;
849 }
850 bool IsMessageDeflated() { return mMessageDeflated; }
851
852 bool UsingContextTakeover() { return !mNoContextTakeover; }
853
854 nsresult Deflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) {
855 if (mResetDeflater || mNoContextTakeover) {
856 if (deflateResetMOZ_Z_deflateReset(&mDeflater) != Z_OK0) {
857 return NS_ERROR_UNEXPECTED;
858 }
859 mResetDeflater = false;
860 }
861
862 mDeflater.avail_out = kBufferLen;
863 mDeflater.next_out = mBuffer;
864 mDeflater.avail_in = dataLen;
865 mDeflater.next_in = data;
866
867 while (true) {
868 int zerr = deflateMOZ_Z_deflate(&mDeflater, Z_SYNC_FLUSH2);
869
870 if (zerr != Z_OK0) {
871 mResetDeflater = true;
872 return NS_ERROR_UNEXPECTED;
873 }
874
875 uint32_t deflated = kBufferLen - mDeflater.avail_out;
876 if (deflated > 0) {
877 _retval.Append(reinterpret_cast<char*>(mBuffer), deflated);
878 }
879
880 mDeflater.avail_out = kBufferLen;
881 mDeflater.next_out = mBuffer;
882
883 if (mDeflater.avail_in > 0) {
884 continue; // There is still some data to deflate
885 }
886
887 if (deflated == kBufferLen) {
888 continue; // There was not enough space in the buffer
889 }
890
891 break;
892 }
893
894 if (_retval.Length() < 4) {
895 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"
, 895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Expected trailing not found in deflated data!" ")"); do { *
((volatile int*)__null) = 895; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
896 mResetDeflater = true;
897 return NS_ERROR_UNEXPECTED;
898 }
899
900 _retval.Truncate(_retval.Length() - 4);
901
902 return NS_OK;
903 }
904
905 nsresult Inflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) {
906 mMessageDeflated = false;
907
908 Bytef trailingData[] = {0x00, 0x00, 0xFF, 0xFF};
909 bool trailingDataUsed = false;
910
911 mInflater.avail_out = kBufferLen;
912 mInflater.next_out = mBuffer;
913 mInflater.avail_in = dataLen;
914 mInflater.next_in = data;
915
916 while (true) {
917 int zerr = inflateMOZ_Z_inflate(&mInflater, Z_NO_FLUSH0);
918
919 if (zerr == Z_STREAM_END1) {
920 Bytef* saveNextIn = mInflater.next_in;
921 uint32_t saveAvailIn = mInflater.avail_in;
922 Bytef* saveNextOut = mInflater.next_out;
923 uint32_t saveAvailOut = mInflater.avail_out;
924
925 inflateResetMOZ_Z_inflateReset(&mInflater);
926
927 mInflater.next_in = saveNextIn;
928 mInflater.avail_in = saveAvailIn;
929 mInflater.next_out = saveNextOut;
930 mInflater.avail_out = saveAvailOut;
931 } else if (zerr != Z_OK0 && zerr != Z_BUF_ERROR(-5)) {
932 return NS_ERROR_INVALID_CONTENT_ENCODING;
933 }
934
935 uint32_t inflated = kBufferLen - mInflater.avail_out;
936 if (inflated > 0) {
937 if (!_retval.Append(reinterpret_cast<char*>(mBuffer), inflated,
938 fallible)) {
939 return NS_ERROR_OUT_OF_MEMORY;
940 }
941 }
942
943 mInflater.avail_out = kBufferLen;
944 mInflater.next_out = mBuffer;
945
946 if (mInflater.avail_in > 0) {
947 continue; // There is still some data to inflate
948 }
949
950 if (inflated == kBufferLen) {
951 continue; // There was not enough space in the buffer
952 }
953
954 if (!trailingDataUsed) {
955 trailingDataUsed = true;
956 mInflater.avail_in = sizeof(trailingData);
957 mInflater.next_in = trailingData;
958 continue;
959 }
960
961 return NS_OK;
962 }
963 }
964
965 private:
966 bool mActive;
967 bool mNoContextTakeover;
968 bool mResetDeflater;
969 bool mMessageDeflated;
970 z_stream mDeflater{};
971 z_stream mInflater{};
972 const static uint32_t kBufferLen = 4096;
973 uint8_t mBuffer[kBufferLen]{0};
974};
975
976//-----------------------------------------------------------------------------
977// OutboundMessage
978//-----------------------------------------------------------------------------
979
980enum WsMsgType {
981 kMsgTypeString = 0,
982 kMsgTypeBinaryString,
983 kMsgTypeStream,
984 kMsgTypePing,
985 kMsgTypePong,
986 kMsgTypeFin
987};
988
989static const char* msgNames[] = {"text", "binaryString", "binaryStream",
990 "ping", "pong", "close"};
991
992class OutboundMessage {
993 public:
994 OutboundMessage(WsMsgType type, const nsACString& str)
995 : mMsg(mozilla::AsVariant(pString(str))),
996 mMsgType(type),
997 mDeflated(false) {
998 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)
;
999 }
1000
1001 OutboundMessage(nsIInputStream* stream, uint32_t length)
1002 : mMsg(mozilla::AsVariant(StreamWithLength(stream, length))),
1003 mMsgType(kMsgTypeStream),
1004 mDeflated(false) {
1005 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)
;
1006 }
1007
1008 ~OutboundMessage() {
1009 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)
;
1010 switch (mMsgType) {
1011 case kMsgTypeString:
1012 case kMsgTypeBinaryString:
1013 case kMsgTypePing:
1014 case kMsgTypePong:
1015 break;
1016 case kMsgTypeStream:
1017 // for now this only gets hit if msg deleted w/o being sent
1018 if (mMsg.as<StreamWithLength>().mStream) {
1019 mMsg.as<StreamWithLength>().mStream->Close();
1020 }
1021 break;
1022 case kMsgTypeFin:
1023 break; // do-nothing: avoid compiler warning
1024 }
1025 }
1026
1027 WsMsgType GetMsgType() const { return mMsgType; }
1028 int32_t Length() {
1029 if (mMsg.is<pString>()) {
1030 return mMsg.as<pString>().mValue.Length();
1031 }
1032
1033 return mMsg.as<StreamWithLength>().mLength;
1034 }
1035 int32_t OrigLength() {
1036 if (mMsg.is<pString>()) {
1037 pString& ref = mMsg.as<pString>();
1038 return mDeflated ? ref.mOrigValue.Length() : ref.mValue.Length();
1039 }
1040
1041 return mMsg.as<StreamWithLength>().mLength;
1042 }
1043
1044 uint8_t* BeginWriting() {
1045 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"
, 1046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1046; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1046 "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"
, 1046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1046; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1047 if (!mMsg.as<pString>().mValue.IsVoid()) {
1048 return (uint8_t*)mMsg.as<pString>().mValue.BeginWriting();
1049 }
1050 return nullptr;
1051 }
1052
1053 uint8_t* BeginReading() {
1054 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"
, 1055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1055; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1055 "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"
, 1055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1055; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1056 if (!mMsg.as<pString>().mValue.IsVoid()) {
1057 return (uint8_t*)mMsg.as<pString>().mValue.BeginReading();
1058 }
1059 return nullptr;
1060 }
1061
1062 uint8_t* BeginOrigReading() {
1063 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"
, 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1064; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1064 "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"
, 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1064; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1065 if (!mDeflated) return BeginReading();
1066 if (!mMsg.as<pString>().mOrigValue.IsVoid()) {
1067 return (uint8_t*)mMsg.as<pString>().mOrigValue.BeginReading();
1068 }
1069 return nullptr;
1070 }
1071
1072 nsresult ConvertStreamToString() {
1073 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"
, 1073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType == kMsgTypeStream"
") (" "Not a stream!" ")"); do { *((volatile int*)__null) = 1073
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1074 nsAutoCString temp;
1075 {
1076 StreamWithLength& ref = mMsg.as<StreamWithLength>();
1077 nsresult rv = NS_ReadInputStreamToString(ref.mStream, temp, ref.mLength);
1078
1079 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"
, 1079); return rv; } } while (false)
;
1080 if (temp.Length() != ref.mLength) {
1081 return NS_ERROR_UNEXPECTED;
1082 }
1083 ref.mStream->Close();
1084 }
1085
1086 mMsg = mozilla::AsVariant(pString(temp));
1087 mMsgType = kMsgTypeBinaryString;
1088
1089 return NS_OK;
1090 }
1091
1092 bool DeflatePayload(PMCECompression* aCompressor) {
1093 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"
, 1094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1094; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1094 "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"
, 1094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream"
") (" "Stream should have been converted to string by now" ")"
); do { *((volatile int*)__null) = 1094; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1095 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"
, 1095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDeflated"
")"); do { *((volatile int*)__null) = 1095; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1096
1097 nsresult rv;
1098 pString& ref = mMsg.as<pString>();
1099 if (ref.mValue.Length() == 0) {
1100 // Empty message
1101 return false;
1102 }
1103
1104 nsAutoCString temp;
1105 rv = aCompressor->Deflate(BeginReading(), ref.mValue.Length(), temp);
1106 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1107 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)
1108 ("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)
1109 "[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)
1110 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)
;
1111 return false;
1112 }
1113
1114 if (!aCompressor->UsingContextTakeover() &&
1115 temp.Length() > ref.mValue.Length()) {
1116 // When "<local>_no_context_takeover" was negotiated, do not send deflated
1117 // payload if it's larger that the original one. OTOH, it makes sense
1118 // to send the larger deflated payload when the sliding window is not
1119 // reset between messages because if we would skip some deflated block
1120 // we would need to empty the sliding window which could affect the
1121 // compression of the subsequent messages.
1122 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)
1123 ("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)
1124 "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)
1125 "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)
1126 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)
;
1127 return false;
1128 }
1129
1130 mDeflated = true;
1131 mMsg.as<pString>().mOrigValue = mMsg.as<pString>().mValue;
1132 mMsg.as<pString>().mValue = temp;
1133 return true;
1134 }
1135
1136 private:
1137 struct pString {
1138 nsCString mValue;
1139 nsCString mOrigValue;
1140 explicit pString(const nsACString& value)
1141 : mValue(value), mOrigValue(VoidCString()) {}
1142 };
1143 struct StreamWithLength {
1144 nsCOMPtr<nsIInputStream> mStream;
1145 uint32_t mLength;
1146 explicit StreamWithLength(nsIInputStream* stream, uint32_t Length)
1147 : mStream(stream), mLength(Length) {}
1148 };
1149 mozilla::Variant<pString, StreamWithLength> mMsg;
1150 WsMsgType mMsgType;
1151 bool mDeflated;
1152};
1153
1154//-----------------------------------------------------------------------------
1155// OutboundEnqueuer
1156//-----------------------------------------------------------------------------
1157
1158class OutboundEnqueuer final : public Runnable {
1159 public:
1160 OutboundEnqueuer(WebSocketChannel* aChannel, OutboundMessage* aMsg)
1161 : Runnable("OutboundEnquerer"), mChannel(aChannel), mMessage(aMsg) {}
1162
1163 NS_IMETHODvirtual nsresult Run() override {
1164 mChannel->EnqueueOutgoingMessage(mChannel->mOutgoingMessages, mMessage);
1165 return NS_OK;
1166 }
1167
1168 private:
1169 ~OutboundEnqueuer() = default;
1170
1171 RefPtr<WebSocketChannel> mChannel;
1172 OutboundMessage* mMessage;
1173};
1174
1175//-----------------------------------------------------------------------------
1176// WebSocketChannel
1177//-----------------------------------------------------------------------------
1178
1179WebSocketChannel::WebSocketChannel()
1180 : mPort(0),
1181 mCloseTimeout(20000),
1182 mOpenTimeout(20000),
1183 mConnecting(NOT_CONNECTING),
1184 mMaxConcurrentConnections(200),
1185 mInnerWindowID(0),
1186 mGotUpgradeOK(0),
1187 mRecvdHttpUpgradeTransport(0),
1188 mPingOutstanding(0),
1189 mReleaseOnTransmit(0),
1190 mDataStarted(false),
1191 mRequestedClose(false),
1192 mClientClosed(false),
1193 mServerClosed(false),
1194 mStopped(false),
1195 mCalledOnStop(false),
1196 mTCPClosed(false),
1197 mOpenedHttpChannel(false),
1198 mIncrementedSessionCount(false),
1199 mDecrementedSessionCount(false),
1200 mMaxMessageSize(INT32_MAX(2147483647)),
1201 mStopOnClose(NS_OK),
1202 mServerCloseCode(CLOSE_ABNORMAL),
1203 mScriptCloseCode(0),
1204 mFragmentOpcode(nsIWebSocketFrame::OPCODE_CONTINUATION),
1205 mFragmentAccumulator(0),
1206 mBuffered(0),
1207 mBufferSize(kIncomingBufferInitialSize),
1208 mCurrentOut(nullptr),
1209 mCurrentOutSent(0),
1210 mHdrOutToSend(0),
1211 mHdrOut(nullptr),
1212 mCompressorMutex("WebSocketChannel::mCompressorMutex"),
1213 mDynamicOutputSize(0),
1214 mDynamicOutput(nullptr),
1215 mPrivateBrowsing(false),
1216 mConnectionLogService(nullptr),
1217 mMutex("WebSocketChannel::mMutex") {
1218 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"
, 1218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
1218; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
1219
1220 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)
;
1221
1222 nsWSAdmissionManager::Init();
1223
1224 mFramePtr = mBuffer = static_cast<uint8_t*>(moz_xmalloc(mBufferSize));
1225
1226 nsresult rv;
1227 mConnectionLogService = mozilla::components::Dashboard::Service(&rv);
1228 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)
;
1229
1230 mService = WebSocketEventService::GetOrCreate();
1231}
1232
1233WebSocketChannel::~WebSocketChannel() {
1234 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)
;
1235
1236 if (mWasOpened) {
1237 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"
, 1237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCalledOnStop"
") (" "WebSocket was opened but OnStop was not called" ")");
do { *((volatile int*)__null) = 1237; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1238 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"
, 1238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") ("
"WebSocket was opened but never stopped" ")"); do { *((volatile
int*)__null) = 1238; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1239 }
1240 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"
, 1240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable"
") (" "DNS/Proxy Request still alive at destruction" ")"); do
{ *((volatile int*)__null) = 1240; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1241 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"
, 1241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnecting"
") (" "Should not be connecting in destructor" ")"); do { *(
(volatile int*)__null) = 1241; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1242
1243 free(mBuffer);
1244 free(mDynamicOutput);
1245 delete mCurrentOut;
1246
1247 while ((mCurrentOut = mOutgoingPingMessages.PopFront())) {
1248 delete mCurrentOut;
1249 }
1250 while ((mCurrentOut = mOutgoingPongMessages.PopFront())) {
1251 delete mCurrentOut;
1252 }
1253 while ((mCurrentOut = mOutgoingMessages.PopFront())) {
1254 delete mCurrentOut;
1255 }
1256
1257 mListenerMT = nullptr;
1258
1259 NS_ReleaseOnMainThread("WebSocketChannel::mService", mService.forget());
1260}
1261
1262NS_IMETHODIMPnsresult
1263WebSocketChannel::Observe(nsISupports* subject, const char* topic,
1264 const char16_t* data) {
1265 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)
;
1266
1267 if (strcmp(topic, NS_NETWORK_LINK_TOPIC"network:link-status-changed") == 0) {
1268 nsCString converted = NS_ConvertUTF16toUTF8(data);
1269 const char* state = converted.get();
1270
1271 if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED"changed") == 0) {
1272 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)
;
1273
1274 if (!mIOThread) {
1275 // there has not been an asyncopen yet on the object and then we need
1276 // no ping.
1277 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)
;
1278 } else {
1279 mIOThread->Dispatch(
1280 NewRunnableMethod("net::WebSocketChannel::OnNetworkChanged", this,
1281 &WebSocketChannel::OnNetworkChanged),
1282 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1283 }
1284 }
1285 }
1286
1287 return NS_OK;
1288}
1289
1290nsresult WebSocketChannel::OnNetworkChanged() {
1291 if (!mDataStarted) {
1292 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)
;
1293 return NS_OK;
1294 }
1295
1296 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"
, 1296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 1296; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1297
1298 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)
;
1299
1300 if (mPingOutstanding) {
1301 // If there's an outstanding ping that's expected to get a pong back
1302 // we let that do its thing.
1303 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)
;
1304 return NS_OK;
1305 }
1306
1307 if (mPingForced) {
1308 // avoid more than one
1309 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)
;
1310 return NS_OK;
1311 }
1312
1313 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)
;
1314
1315 if (!mPingTimer) {
1316 // The ping timer is only conditionally running already. If it wasn't
1317 // already created do it here.
1318 mPingTimer = NS_NewTimer();
1319 if (!mPingTimer) {
1320 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)
;
1321 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"
, 1321)
;
1322 return NS_ERROR_OUT_OF_MEMORY;
1323 }
1324 }
1325 // Trigger the ping timeout asap to fire off a new ping. Wait just
1326 // a little bit to better avoid multi-triggers.
1327 mPingForced = true;
1328 mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT);
1329
1330 return NS_OK;
1331}
1332
1333void WebSocketChannel::Shutdown() { nsWSAdmissionManager::Shutdown(); }
1334
1335void WebSocketChannel::GetEffectiveURL(nsAString& aEffectiveURL) const {
1336 aEffectiveURL = mEffectiveURL;
1337}
1338
1339bool WebSocketChannel::IsEncrypted() const { return mEncrypted; }
1340
1341void WebSocketChannel::BeginOpen(bool aCalledFromAdmissionManager) {
1342 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"
, 1342); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
1342; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
1343
1344 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)
;
1345
1346 // Important that we set CONNECTING_IN_PROGRESS before any call to
1347 // AbortSession here: ensures that any remaining queued connection(s) are
1348 // scheduled in OnStopSession
1349 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)
;
1350 mConnecting = CONNECTING_IN_PROGRESS;
1351
1352 if (aCalledFromAdmissionManager) {
1353 // When called from nsWSAdmissionManager post an event to avoid potential
1354 // re-entering of nsWSAdmissionManager and its lock.
1355 NS_DispatchToMainThread(
1356 NewRunnableMethod("net::WebSocketChannel::BeginOpenInternal", this,
1357 &WebSocketChannel::BeginOpenInternal),
1358 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1359 } else {
1360 BeginOpenInternal();
1361 }
1362}
1363
1364// MainThread
1365void WebSocketChannel::BeginOpenInternal() {
1366 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)
;
1367 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"
, 1367); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
1367; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
1368
1369 nsresult rv;
1370
1371 if (mRedirectCallback) {
1372 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)
;
1373 rv = mRedirectCallback->OnRedirectVerifyCallback(NS_OK);
1374 mRedirectCallback = nullptr;
1375 return;
1376 }
1377
1378 nsCOMPtr<nsIChannel> localChannel = do_QueryInterface(mChannel, &rv);
1379 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1380 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)
;
1381 AbortSession(NS_ERROR_UNEXPECTED);
1382 return;
1383 }
1384
1385 rv = localChannel->AsyncOpen(this);
1386
1387 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1388 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)
;
1389 AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED);
1390 return;
1391 }
1392 mOpenedHttpChannel = true;
1393
1394 rv = NS_NewTimerWithCallback(getter_AddRefs(mOpenTimer), this, mOpenTimeout,
1395 nsITimer::TYPE_ONE_SHOT);
1396 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1397 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)
1398 ("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)
1399 "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)
;
1400 AbortSession(NS_ERROR_UNEXPECTED);
1401 return;
1402 }
1403}
1404
1405bool WebSocketChannel::IsPersistentFramePtr() {
1406 return (mFramePtr >= mBuffer && mFramePtr < mBuffer + mBufferSize);
1407}
1408
1409// Extends the internal buffer by count and returns the total
1410// amount of data available for read
1411//
1412// Accumulated fragment size is passed in instead of using the member
1413// variable beacuse when transitioning from the stack to the persistent
1414// read buffer we want to explicitly include them in the buffer instead
1415// of as already existing data.
1416bool WebSocketChannel::UpdateReadBuffer(uint8_t* buffer, uint32_t count,
1417 uint32_t accumulatedFragments,
1418 uint32_t* available) {
1419 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)
1420 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)
;
1421
1422 if (!mBuffered) mFramePtr = mBuffer;
1423
1424 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"
, 1424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPersistentFramePtr()"
") (" "update read buffer bad mFramePtr" ")"); do { *((volatile
int*)__null) = 1424; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1425 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"
, 1426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer"
") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null
) = 1426; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
1426 "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"
, 1426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer"
") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null
) = 1426; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1427
1428 if (mBuffered + count <= mBufferSize) {
1429 // append to existing buffer
1430 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)
;
1431 } else if (mBuffered + count - (mFramePtr - accumulatedFragments - mBuffer) <=
1432 mBufferSize) {
1433 // make room in existing buffer by shifting unused data to start
1434 mBuffered -= (mFramePtr - mBuffer - accumulatedFragments);
1435 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)
;
1436 ::memmove(mBuffer, mFramePtr - accumulatedFragments, mBuffered);
1437 mFramePtr = mBuffer + accumulatedFragments;
1438 } else {
1439 // existing buffer is not sufficient, extend it
1440 mBufferSize += count + 8192 + mBufferSize / 3;
1441 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)
;
1442 uint8_t* old = mBuffer;
1443 mBuffer = (uint8_t*)realloc(mBuffer, mBufferSize);
1444 if (!mBuffer) {
1445 mBuffer = old;
1446 return false;
1447 }
1448 mFramePtr = mBuffer + (mFramePtr - old);
1449 }
1450
1451 ::memcpy(mBuffer + mBuffered, buffer, count);
1452 mBuffered += count;
1453
1454 if (available) *available = mBuffered - (mFramePtr - mBuffer);
1455
1456 return true;
1457}
1458
1459nsresult WebSocketChannel::ProcessInput(uint8_t* buffer, uint32_t count) {
1460 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)
;
1461 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"
, 1461); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 1461; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1462
1463 nsresult rv;
1464
1465 // The purpose of ping/pong is to actively probe the peer so that an
1466 // unreachable peer is not mistaken for a period of idleness. This
1467 // implementation accepts any application level read activity as a sign of
1468 // life, it does not necessarily have to be a pong.
1469 ResetPingTimer();
1470
1471 uint32_t avail;
1472
1473 if (!mBuffered) {
1474 // Most of the time we can process right off the stack buffer without
1475 // having to accumulate anything
1476 mFramePtr = buffer;
1477 avail = count;
1478 } else {
1479 if (!UpdateReadBuffer(buffer, count, mFragmentAccumulator, &avail)) {
1480 return NS_ERROR_FILE_TOO_BIG;
1481 }
1482 }
1483
1484 uint8_t* payload;
1485 uint32_t totalAvail = avail;
1486
1487 while (avail >= 2) {
1488 int64_t payloadLength64 = mFramePtr[1] & kPayloadLengthBitsMask;
1489 uint8_t finBit = mFramePtr[0] & kFinalFragBit;
1490 uint8_t rsvBits = mFramePtr[0] & kRsvBitsMask;
1491 uint8_t rsvBit1 = mFramePtr[0] & kRsv1Bit;
1492 uint8_t rsvBit2 = mFramePtr[0] & kRsv2Bit;
1493 uint8_t rsvBit3 = mFramePtr[0] & kRsv3Bit;
1494 uint8_t opcode = mFramePtr[0] & kOpcodeBitsMask;
1495 uint8_t maskBit = mFramePtr[1] & kMaskBit;
1496 uint32_t mask = 0;
1497
1498 uint32_t framingLength = 2;
1499 if (maskBit) framingLength += 4;
1500
1501 if (payloadLength64 < 126) {
1502 if (avail < framingLength) break;
1503 } else if (payloadLength64 == 126) {
1504 // 16 bit length field
1505 framingLength += 2;
1506 if (avail < framingLength) break;
1507
1508 payloadLength64 = mFramePtr[2] << 8 | mFramePtr[3];
1509
1510 if (payloadLength64 < 126) {
1511 // Section 5.2 says that the minimal number of bytes MUST
1512 // be used to encode the length in all cases
1513 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)
;
1514 return NS_ERROR_ILLEGAL_VALUE;
1515 }
1516
1517 } else {
1518 // 64 bit length
1519 framingLength += 8;
1520 if (avail < framingLength) break;
1521
1522 if (mFramePtr[2] & 0x80) {
1523 // Section 4.2 says that the most significant bit MUST be
1524 // 0. (i.e. this is really a 63 bit value)
1525 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)
;
1526 return NS_ERROR_ILLEGAL_VALUE;
1527 }
1528
1529 // copy this in case it is unaligned
1530 payloadLength64 = NetworkEndian::readInt64(mFramePtr + 2);
1531
1532 if (payloadLength64 <= 0xffff) {
1533 // Section 5.2 says that the minimal number of bytes MUST
1534 // be used to encode the length in all cases
1535 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)
;
1536 return NS_ERROR_ILLEGAL_VALUE;
1537 }
1538 }
1539
1540 payload = mFramePtr + framingLength;
1541 avail -= framingLength;
1542
1543 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)
1544 "\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)
1545 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)
;
1546
1547 CheckedInt<int64_t> payloadLengthChecked(payloadLength64);
1548 payloadLengthChecked += mFragmentAccumulator;
1549 if (!payloadLengthChecked.isValid() ||
1550 payloadLengthChecked.value() > mMaxMessageSize) {
1551 return NS_ERROR_FILE_TOO_BIG;
1552 }
1553
1554 uint32_t payloadLength = static_cast<uint32_t>(payloadLength64);
1555
1556 if (avail < payloadLength) break;
1557
1558 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)
1559 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)
;
1560
1561 if (!maskBit && mIsServerSide) {
1562 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)
1563 ("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)
1564 "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)
;
1565 return NS_ERROR_ILLEGAL_VALUE;
1566 }
1567
1568 if (maskBit) {
1569 if (!mIsServerSide) {
1570 // The server should not be allowed to send masked frames to clients.
1571 // But we've been allowing it for some time, so this should be
1572 // deprecated with care.
1573 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)
;
1574 }
1575
1576 mask = NetworkEndian::readUint32(payload - 4);
1577 }
1578
1579 if (mask) {
1580 ApplyMask(mask, payload, payloadLength);
1581 } else if (mIsServerSide) {
1582 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)
1583 ("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)
1584 "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)
;
1585 return NS_ERROR_ILLEGAL_VALUE;
1586 }
1587
1588 // Control codes are required to have the fin bit set
1589 if (!finBit && (opcode & kControlFrameMask)) {
1590 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)
;
1591 return NS_ERROR_ILLEGAL_VALUE;
1592 }
1593
1594 if (rsvBits) {
1595 // PMCE sets RSV1 bit in the first fragment when the non-control frame
1596 // is deflated
1597 MutexAutoLock lock(mCompressorMutex);
1598 if (mPMCECompressor && rsvBits == kRsv1Bit && mFragmentAccumulator == 0 &&
1599 !(opcode & kControlFrameMask)) {
1600 mPMCECompressor->SetMessageDeflated();
1601 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)
;
1602 } else {
1603 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)
1604 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)
;
1605 return NS_ERROR_ILLEGAL_VALUE;
1606 }
1607 }
1608
1609 if (!finBit || opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) {
1610 // This is part of a fragment response
1611
1612 // Only the first frame has a non zero op code: Make sure we don't see a
1613 // first frame while some old fragments are open
1614 if ((mFragmentAccumulator != 0) &&
1615 (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION)) {
1616 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)
;
1617 return NS_ERROR_ILLEGAL_VALUE;
1618 }
1619
1620 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)
1621 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)
;
1622
1623 if (opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) {
1624 // Make sure this continuation fragment isn't the first fragment
1625 if (mFragmentOpcode == nsIWebSocketFrame::OPCODE_CONTINUATION) {
1626 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)
;
1627 return NS_ERROR_ILLEGAL_VALUE;
1628 }
1629
1630 // For frag > 1 move the data body back on top of the headers
1631 // so we have contiguous stream of data
1632 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"
, 1633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1633; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1633 "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"
, 1633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1633; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1634 ::memmove(mFramePtr, payload, avail);
1635 payload = mFramePtr;
1636 if (mBuffered) mBuffered -= framingLength;
1637 } else {
1638 mFragmentOpcode = opcode;
1639 }
1640
1641 if (finBit) {
1642 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)
;
1643 payload -= mFragmentAccumulator;
1644 payloadLength += mFragmentAccumulator;
1645 avail += mFragmentAccumulator;
1646 mFragmentAccumulator = 0;
1647 opcode = mFragmentOpcode;
1648 // reset to detect if next message illegally starts with continuation
1649 mFragmentOpcode = nsIWebSocketFrame::OPCODE_CONTINUATION;
1650 } else {
1651 opcode = nsIWebSocketFrame::OPCODE_CONTINUATION;
1652 mFragmentAccumulator += payloadLength;
1653 }
1654 } else if (mFragmentAccumulator != 0 && !(opcode & kControlFrameMask)) {
1655 // This frame is not part of a fragment sequence but we
1656 // have an open fragment.. it must be a control code or else
1657 // we have a problem
1658 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)
;
1659 return NS_ERROR_ILLEGAL_VALUE;
1660 }
1661
1662 if (mServerClosed) {
1663 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)
1664 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)
;
1665 // nop
1666 } else if (mStopped) {
1667 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)
1668 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)
;
1669 } else if (opcode == nsIWebSocketFrame::OPCODE_TEXT) {
1670 if (mListenerMT) {
1671 nsCString utf8Data;
1672 {
1673 MutexAutoLock lock(mCompressorMutex);
1674 bool isDeflated =
1675 mPMCECompressor && mPMCECompressor->IsMessageDeflated();
1676 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)
1677 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)
;
1678
1679 if (isDeflated) {
1680 rv = mPMCECompressor->Inflate(payload, payloadLength, utf8Data);
1681 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1682 return rv;
1683 }
1684 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)
1685 ("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)
1686 "[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)
1687 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)
;
1688 } else {
1689 if (!utf8Data.Assign((const char*)payload, payloadLength,
1690 mozilla::fallible)) {
1691 return NS_ERROR_OUT_OF_MEMORY;
1692 }
1693 }
1694 }
1695
1696 // Section 8.1 says to fail connection if invalid utf-8 in text message
1697 if (!IsUtf8(utf8Data)) {
1698 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)
;
1699 return NS_ERROR_CANNOT_CONVERT_DATA;
1700 }
1701
1702 RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded(
1703 finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, utf8Data);
1704
1705 if (frame) {
1706 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1707 }
1708
1709 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
1710 target->Dispatch(new CallOnMessageAvailable(this, utf8Data, -1),
1711 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1712 } else {
1713 return NS_ERROR_UNEXPECTED;
1714 }
1715 if (mConnectionLogService && !mPrivateBrowsing) {
1716 mConnectionLogService->NewMsgReceived(mHost, mSerial, count);
1717 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)
;
1718 }
1719 }
1720 } else if (opcode & kControlFrameMask) {
1721 // control frames
1722 if (payloadLength > 125) {
1723 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)
1724 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)
;
1725 return NS_ERROR_ILLEGAL_VALUE;
1726 }
1727
1728 RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded(
1729 finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, payload,
1730 payloadLength);
1731
1732 if (opcode == nsIWebSocketFrame::OPCODE_CLOSE) {
1733 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)
;
1734 mServerClosed = true;
1735
1736 mServerCloseCode = CLOSE_NO_STATUS;
1737 if (payloadLength >= 2) {
1738 mServerCloseCode = NetworkEndian::readUint16(payload);
1739 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)
;
1740 uint16_t msglen = static_cast<uint16_t>(payloadLength - 2);
1741 if (msglen > 0) {
1742 mServerCloseReason.SetLength(msglen);
1743 memcpy(mServerCloseReason.BeginWriting(), (const char*)payload + 2,
1744 msglen);
1745
1746 // section 8.1 says to replace received non utf-8 sequences
1747 // (which are non-conformant to send) with u+fffd,
1748 // but secteam feels that silently rewriting messages is
1749 // inappropriate - so we will fail the connection instead.
1750 if (!IsUtf8(mServerCloseReason)) {
1751 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)
;
1752 return NS_ERROR_CANNOT_CONVERT_DATA;
1753 }
1754
1755 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)
1756 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)
;
1757 }
1758 }
1759
1760 if (mCloseTimer) {
1761 mCloseTimer->Cancel();
1762 mCloseTimer = nullptr;
1763 }
1764
1765 if (frame) {
1766 // We send the frame immediately becuase we want to have it dispatched
1767 // before the CallOnServerClose.
1768 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1769 frame = nullptr;
1770 }
1771
1772 if (mListenerMT) {
1773 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
1774 target->Dispatch(new CallOnServerClose(this, mServerCloseCode,
1775 mServerCloseReason),
1776 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1777 } else {
1778 return NS_ERROR_UNEXPECTED;
1779 }
1780 }
1781
1782 if (mClientClosed) ReleaseSession();
1783 } else if (opcode == nsIWebSocketFrame::OPCODE_PING) {
1784 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)
;
1785 GeneratePong(payload, payloadLength);
1786 } else if (opcode == nsIWebSocketFrame::OPCODE_PONG) {
1787 // opcode OPCODE_PONG: the mere act of receiving the packet is all we
1788 // need to do for the pong to trigger the activity timers
1789 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)
;
1790 } else {
1791 /* unknown control frame opcode */
1792 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)
;
1793 return NS_ERROR_ILLEGAL_VALUE;
1794 }
1795
1796 if (mFragmentAccumulator) {
1797 // Remove the control frame from the stream so we have a contiguous
1798 // data buffer of reassembled fragments
1799 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)
;
1800 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"
, 1801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1801; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1801 "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"
, 1801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload"
") (" "payload offset from frameptr wrong" ")"); do { *((volatile
int*)__null) = 1801; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1802 ::memmove(mFramePtr, payload + payloadLength, avail - payloadLength);
1803 payload = mFramePtr;
1804 avail -= payloadLength;
1805 if (mBuffered) mBuffered -= framingLength + payloadLength;
1806 payloadLength = 0;
1807 }
1808
1809 if (frame) {
1810 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1811 }
1812 } else if (opcode == nsIWebSocketFrame::OPCODE_BINARY) {
1813 if (mListenerMT) {
1814 nsCString binaryData;
1815 {
1816 MutexAutoLock lock(mCompressorMutex);
1817 bool isDeflated =
1818 mPMCECompressor && mPMCECompressor->IsMessageDeflated();
1819 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)
1820 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)
;
1821
1822 if (isDeflated) {
1823 rv = mPMCECompressor->Inflate(payload, payloadLength, binaryData);
1824 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1825 return rv;
1826 }
1827 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)
1828 ("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)
1829 "[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)
1830 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)
;
1831 } else {
1832 if (!binaryData.Assign((const char*)payload, payloadLength,
1833 mozilla::fallible)) {
1834 return NS_ERROR_OUT_OF_MEMORY;
1835 }
1836 }
1837 }
1838
1839 RefPtr<WebSocketFrame> frame =
1840 mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3,
1841 opcode, maskBit, mask, binaryData);
1842 if (frame) {
1843 mService->FrameReceived(mSerial, mInnerWindowID, frame.forget());
1844 }
1845
1846 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
1847 target->Dispatch(
1848 new CallOnMessageAvailable(this, binaryData, binaryData.Length()),
1849 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1850 } else {
1851 return NS_ERROR_UNEXPECTED;
1852 }
1853 // To add the header to 'Networking Dashboard' log
1854 if (mConnectionLogService && !mPrivateBrowsing) {
1855 mConnectionLogService->NewMsgReceived(mHost, mSerial, count);
1856 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)
;
1857 }
1858 }
1859 } else if (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION) {
1860 /* unknown opcode */
1861 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)
;
1862 return NS_ERROR_ILLEGAL_VALUE;
1863 }
1864
1865 mFramePtr = payload + payloadLength;
1866 avail -= payloadLength;
1867 totalAvail = avail;
1868 }
1869
1870 // Adjust the stateful buffer. If we were operating off the stack and
1871 // now have a partial message then transition to the buffer, or if
1872 // we were working off the buffer but no longer have any active state
1873 // then transition to the stack
1874 if (!IsPersistentFramePtr()) {
1875 mBuffered = 0;
1876
1877 if (mFragmentAccumulator) {
1878 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)
;
1879
1880 if (!UpdateReadBuffer(mFramePtr - mFragmentAccumulator,
1881 totalAvail + mFragmentAccumulator, 0, nullptr)) {
1882 return NS_ERROR_FILE_TOO_BIG;
1883 }
1884
1885 // UpdateReadBuffer will reset the frameptr to the beginning
1886 // of new saved state, so we need to skip past processed framgents
1887 mFramePtr += mFragmentAccumulator;
1888 } else if (totalAvail) {
1889 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)
;
1890 if (!UpdateReadBuffer(mFramePtr, totalAvail, 0, nullptr)) {
1891 return NS_ERROR_FILE_TOO_BIG;
1892 }
1893 }
1894 } else if (!mFragmentAccumulator && !totalAvail) {
1895 // If we were working off a saved buffer state and there is no partial
1896 // frame or fragment in process, then revert to stack behavior
1897 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)
;
1898 mBuffered = 0;
1899
1900 // release memory if we've been processing a large message
1901 if (mBufferSize > kIncomingBufferStableSize) {
1902 mBufferSize = kIncomingBufferStableSize;
1903 free(mBuffer);
1904 mBuffer = (uint8_t*)moz_xmalloc(mBufferSize);
1905 }
1906 }
1907 return NS_OK;
1908}
1909
1910/* static */
1911void WebSocketChannel::ApplyMask(uint32_t mask, uint8_t* data, uint64_t len) {
1912 if (!data || len == 0) return;
1913
1914 // Optimally we want to apply the mask 32 bits at a time,
1915 // but the buffer might not be alligned. So we first deal with
1916 // 0 to 3 bytes of preamble individually
1917
1918 while (len && (reinterpret_cast<uintptr_t>(data) & 3)) {
1919 *data ^= mask >> 24;
1920 mask = RotateLeft(mask, 8);
1921 data++;
1922 len--;
1923 }
1924
1925 // perform mask on full words of data
1926
1927 uint32_t* iData = (uint32_t*)data;
1928 uint32_t* end = iData + (len / 4);
1929 NetworkEndian::writeUint32(&mask, mask);
1930 for (; iData < end; iData++) *iData ^= mask;
1931 mask = NetworkEndian::readUint32(&mask);
1932 data = (uint8_t*)iData;
1933 len = len % 4;
1934
1935 // There maybe up to 3 trailing bytes that need to be dealt with
1936 // individually
1937
1938 while (len) {
1939 *data ^= mask >> 24;
1940 mask = RotateLeft(mask, 8);
1941 data++;
1942 len--;
1943 }
1944}
1945
1946void WebSocketChannel::GeneratePing() {
1947 nsAutoCString buf;
1948 buf.AssignLiteral("PING");
1949 EnqueueOutgoingMessage(mOutgoingPingMessages,
1950 new OutboundMessage(kMsgTypePing, buf));
1951}
1952
1953void WebSocketChannel::GeneratePong(uint8_t* payload, uint32_t len) {
1954 nsAutoCString buf;
1955 buf.SetLength(len);
1956 if (buf.Length() < len) {
1957 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)
;
1958 return;
1959 }
1960
1961 memcpy(buf.BeginWriting(), payload, len);
1962 EnqueueOutgoingMessage(mOutgoingPongMessages,
1963 new OutboundMessage(kMsgTypePong, buf));
1964}
1965
1966void WebSocketChannel::EnqueueOutgoingMessage(nsDeque<OutboundMessage>& aQueue,
1967 OutboundMessage* aMsg) {
1968 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"
, 1968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 1968; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1969
1970 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)
1971 ("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)
1972 "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)
1973 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)
;
1974
1975 aQueue.Push(aMsg);
1976 if (mSocketOut) {
1977 OnOutputStreamReady(mSocketOut);
1978 } else {
1979 DoEnqueueOutgoingMessage();
1980 }
1981}
1982
1983uint16_t WebSocketChannel::ResultToCloseCode(nsresult resultCode) {
1984 if (NS_SUCCEEDED(resultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(resultCode)), 1))
)
) return CLOSE_NORMAL;
1985
1986 switch (resultCode) {
1987 case NS_ERROR_FILE_TOO_BIG:
1988 case NS_ERROR_OUT_OF_MEMORY:
1989 return CLOSE_TOO_LARGE;
1990 case NS_ERROR_CANNOT_CONVERT_DATA:
1991 return CLOSE_INVALID_PAYLOAD;
1992 case NS_ERROR_UNEXPECTED:
1993 return CLOSE_INTERNAL_ERROR;
1994 default:
1995 return CLOSE_PROTOCOL_ERROR;
1996 }
1997}
1998
1999void WebSocketChannel::PrimeNewOutgoingMessage() {
2000 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)
;
2001 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"
, 2001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 2001; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2002 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"
, 2002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCurrentOut"
") (" "Current message in progress" ")"); do { *((volatile int
*)__null) = 2002; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2003
2004 nsresult rv = NS_OK;
2005
2006 mCurrentOut = mOutgoingPongMessages.PopFront();
2007 if (mCurrentOut) {
2008 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"
, 2008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePong"
") (" "Not pong message!" ")"); do { *((volatile int*)__null
) = 2008; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2009 } else {
2010 mCurrentOut = mOutgoingPingMessages.PopFront();
2011 if (mCurrentOut) {
2012 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"
, 2013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing"
") (" "Not ping message!" ")"); do { *((volatile int*)__null
) = 2013; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2013 "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"
, 2013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing"
") (" "Not ping message!" ")"); do { *((volatile int*)__null
) = 2013; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2014 } else {
2015 mCurrentOut = mOutgoingMessages.PopFront();
2016 }
2017 }
2018
2019 if (!mCurrentOut) return;
2020
2021 auto cleanupAfterFailure =
2022 MakeScopeExit([&] { DeleteCurrentOutGoingMessage(); });
2023
2024 WsMsgType msgType = mCurrentOut->GetMsgType();
2025
2026 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)
2027 ("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)
2028 "%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)
2029 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)
;
2030
2031 mCurrentOutSent = 0;
2032 mHdrOut = mOutHeader;
2033
2034 uint8_t maskBit = mIsServerSide ? 0 : kMaskBit;
2035 uint8_t maskSize = mIsServerSide ? 0 : 4;
2036
2037 uint8_t* payload = nullptr;
2038
2039 if (msgType == kMsgTypeFin) {
2040 // This is a demand to create a close message
2041 if (mClientClosed) {
2042 DeleteCurrentOutGoingMessage();
2043 PrimeNewOutgoingMessage();
2044 cleanupAfterFailure.release();
2045 return;
2046 }
2047
2048 mClientClosed = true;
2049 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_CLOSE;
2050 mOutHeader[1] = maskBit;
2051
2052 // payload is offset 2 plus size of the mask
2053 payload = mOutHeader + 2 + maskSize;
2054
2055 // The close reason code sits in the first 2 bytes of payload
2056 // If the channel user provided a code and reason during Close()
2057 // and there isn't an internal error, use that.
2058 if (NS_SUCCEEDED(mStopOnClose)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStopOnClose)), 1
)))
) {
2059 MutexAutoLock lock(mMutex);
2060 if (mScriptCloseCode) {
2061 NetworkEndian::writeUint16(payload, mScriptCloseCode);
2062 mOutHeader[1] += 2;
2063 mHdrOutToSend = 4 + maskSize;
2064 if (!mScriptCloseReason.IsEmpty()) {
2065 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"
, 2066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123"
") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null
) = 2066; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2066 "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"
, 2066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123"
") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null
) = 2066; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2067 mOutHeader[1] += mScriptCloseReason.Length();
2068 mHdrOutToSend += mScriptCloseReason.Length();
2069 memcpy(payload + 2, mScriptCloseReason.BeginReading(),
2070 mScriptCloseReason.Length());
2071 }
2072 } else {
2073 // No close code/reason, so payload length = 0. We must still send mask
2074 // even though it's not used. Keep payload offset so we write mask
2075 // below.
2076 mHdrOutToSend = 2 + maskSize;
2077 }
2078 } else {
2079 NetworkEndian::writeUint16(payload, ResultToCloseCode(mStopOnClose));
2080 mOutHeader[1] += 2;
2081 mHdrOutToSend = 4 + maskSize;
2082 }
2083
2084 if (mServerClosed) {
2085 /* bidi close complete */
2086 mReleaseOnTransmit = 1;
2087 } else if (NS_FAILED(mStopOnClose)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStopOnClose)), 0)
))
) {
2088 /* result of abort session - give up */
2089 StopSession(mStopOnClose);
2090 } else {
2091 /* wait for reciprocal close from server */
2092 rv = NS_NewTimerWithCallback(getter_AddRefs(mCloseTimer), this,
2093 mCloseTimeout, nsITimer::TYPE_ONE_SHOT);
2094 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2095 StopSession(rv);
2096 }
2097 }
2098 } else {
2099 switch (msgType) {
2100 case kMsgTypePong:
2101 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PONG;
2102 break;
2103 case kMsgTypePing:
2104 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PING;
2105 break;
2106 case kMsgTypeString:
2107 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_TEXT;
2108 break;
2109 case kMsgTypeStream:
2110 // HACK ALERT: read in entire stream into string.
2111 // Will block socket transport thread if file is blocking.
2112 // TODO: bug 704447: don't block socket thread!
2113 rv = mCurrentOut->ConvertStreamToString();
2114 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2115 AbortSession(NS_ERROR_FILE_TOO_BIG);
2116 return;
2117 }
2118 // Now we're a binary string
2119 msgType = kMsgTypeBinaryString;
2120
2121 // no break: fall down into binary string case
2122 [[fallthrough]];
2123
2124 case kMsgTypeBinaryString:
2125 mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_BINARY;
2126 break;
2127 case kMsgTypeFin:
2128 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"
, 2128); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"unreachable" ")"); do { *((volatile int*)__null) = 2128; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
; // avoid compiler warning
2129 break;
2130 }
2131
2132 // deflate the payload if PMCE is negotiated
2133 MutexAutoLock lock(mCompressorMutex);
2134 if (mPMCECompressor &&
2135 (msgType == kMsgTypeString || msgType == kMsgTypeBinaryString)) {
2136 if (mCurrentOut->DeflatePayload(mPMCECompressor.get())) {
2137 // The payload was deflated successfully, set RSV1 bit
2138 mOutHeader[0] |= kRsv1Bit;
2139
2140 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)
2141 ("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)
2142 "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)
2143 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)
2144 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)
;
2145 }
2146 }
2147
2148 if (mCurrentOut->Length() < 126) {
2149 mOutHeader[1] = mCurrentOut->Length() | maskBit;
2150 mHdrOutToSend = 2 + maskSize;
2151 } else if (mCurrentOut->Length() <= 0xffff) {
2152 mOutHeader[1] = 126 | maskBit;
2153 NetworkEndian::writeUint16(mOutHeader + sizeof(uint16_t),
2154 mCurrentOut->Length());
2155 mHdrOutToSend = 4 + maskSize;
2156 } else {
2157 mOutHeader[1] = 127 | maskBit;
2158 NetworkEndian::writeUint64(mOutHeader + 2, mCurrentOut->Length());
2159 mHdrOutToSend = 10 + maskSize;
2160 }
2161 payload = mOutHeader + mHdrOutToSend;
2162 }
2163
2164 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"
, 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "payload" ") ("
"payload offset not found" ")"); do { *((volatile int*)__null
) = 2164; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2165
2166 uint32_t mask = 0;
2167 if (!mIsServerSide) {
2168 // Perform the sending mask. Never use a zero mask
2169 do {
2170 static_assert(4 == sizeof(mask), "Size of the mask should be equal to 4");
2171 nsresult rv = mRandomGenerator->GenerateRandomBytesInto(mask);
2172 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2173 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)
2174 ("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)
2175 "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)
2176 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)
;
2177 AbortSession(rv);
2178 return;
2179 }
2180 } while (!mask);
2181 NetworkEndian::writeUint32(payload - sizeof(uint32_t), mask);
2182 }
2183
2184 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)
;
2185
2186 // We don't mask the framing, but occasionally we stick a little payload
2187 // data in the buffer used for the framing. Close frames are the current
2188 // example. This data needs to be masked, but it is never more than a
2189 // handful of bytes and might rotate the mask, so we can just do it locally.
2190 // For real data frames we ship the bulk of the payload off to ApplyMask()
2191
2192 RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded(
2193 mOutHeader[0] & WebSocketChannel::kFinalFragBit,
2194 mOutHeader[0] & WebSocketChannel::kRsv1Bit,
2195 mOutHeader[0] & WebSocketChannel::kRsv2Bit,
2196 mOutHeader[0] & WebSocketChannel::kRsv3Bit,
2197 mOutHeader[0] & WebSocketChannel::kOpcodeBitsMask,
2198 mOutHeader[1] & WebSocketChannel::kMaskBit, mask, payload,
2199 mHdrOutToSend - (payload - mOutHeader), mCurrentOut->BeginOrigReading(),
2200 mCurrentOut->OrigLength());
2201
2202 if (frame) {
2203 mService->FrameSent(mSerial, mInnerWindowID, frame.forget());
2204 }
2205
2206 if (mask) {
2207 while (payload < (mOutHeader + mHdrOutToSend)) {
2208 *payload ^= mask >> 24;
2209 mask = RotateLeft(mask, 8);
2210 payload++;
2211 }
2212
2213 // Mask the real message payloads
2214 ApplyMask(mask, mCurrentOut->BeginWriting(), mCurrentOut->Length());
2215 }
2216
2217 int32_t len = mCurrentOut->Length();
2218
2219 // for small frames, copy it all together for a contiguous write
2220 if (len && len <= kCopyBreak) {
2221 memcpy(mOutHeader + mHdrOutToSend, mCurrentOut->BeginWriting(), len);
2222 mHdrOutToSend += len;
2223 mCurrentOutSent = len;
2224 }
2225
2226 // Transmitting begins - mHdrOutToSend bytes from mOutHeader and
2227 // mCurrentOut->Length() bytes from mCurrentOut. The latter may be
2228 // coaleseced into the former for small messages or as the result of the
2229 // compression process.
2230
2231 cleanupAfterFailure.release();
2232}
2233
2234void WebSocketChannel::DeleteCurrentOutGoingMessage() {
2235 delete mCurrentOut;
2236 mCurrentOut = nullptr;
2237 mCurrentOutSent = 0;
2238}
2239
2240void WebSocketChannel::EnsureHdrOut(uint32_t size) {
2241 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)
;
2242
2243 if (mDynamicOutputSize < size) {
2244 mDynamicOutputSize = size;
2245 mDynamicOutput = (uint8_t*)moz_xrealloc(mDynamicOutput, mDynamicOutputSize);
2246 }
2247
2248 mHdrOut = mDynamicOutput;
2249}
2250
2251namespace {
2252
2253class RemoveObserverRunnable : public Runnable {
2254 RefPtr<WebSocketChannel> mChannel;
2255
2256 public:
2257 explicit RemoveObserverRunnable(WebSocketChannel* aChannel)
2258 : Runnable("net::RemoveObserverRunnable"), mChannel(aChannel) {}
2259
2260 NS_IMETHODvirtual nsresult Run() override {
2261 nsCOMPtr<nsIObserverService> observerService =
2262 mozilla::services::GetObserverService();
2263 if (!observerService) {
2264 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"
, 2264)
;
2265 return NS_OK;
2266 }
2267
2268 observerService->RemoveObserver(mChannel, NS_NETWORK_LINK_TOPIC"network:link-status-changed");
2269 return NS_OK;
2270 }
2271};
2272
2273} // namespace
2274
2275void WebSocketChannel::CleanupConnection() {
2276 // normally this should be called on socket thread, but it may be called
2277 // on MainThread
2278
2279 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)
;
2280 // This needs to run on the IOThread so we don't need to lock a bunch of these
2281 if (!mIOThread->IsOnCurrentThread()) {
2282 mIOThread->Dispatch(
2283 NewRunnableMethod("net::WebSocketChannel::CleanupConnection", this,
2284 &WebSocketChannel::CleanupConnection),
2285 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2286 return;
2287 }
2288
2289 if (mLingeringCloseTimer) {
2290 mLingeringCloseTimer->Cancel();
2291 mLingeringCloseTimer = nullptr;
2292 }
2293
2294 if (mSocketIn) {
2295 if (mDataStarted) {
2296 mSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
2297 }
2298 mSocketIn = nullptr;
2299 }
2300
2301 if (mSocketOut) {
2302 mSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
2303 mSocketOut = nullptr;
2304 }
2305
2306 if (mTransport) {
2307 mTransport->SetSecurityCallbacks(nullptr);
2308 mTransport->SetEventSink(nullptr, nullptr);
2309 mTransport->Close(NS_BASE_STREAM_CLOSED);
2310 mTransport = nullptr;
2311 }
2312
2313 if (mConnection) {
2314 mConnection->Close();
2315 mConnection = nullptr;
2316 }
2317
2318 if (mConnectionLogService && !mPrivateBrowsing) {
2319 mConnectionLogService->RemoveHost(mHost, mSerial);
2320 }
2321
2322 // The observer has to be removed on the main-thread.
2323 NS_DispatchToMainThread(new RemoveObserverRunnable(this));
2324
2325 DecrementSessionCount();
2326}
2327
2328void WebSocketChannel::StopSession(nsresult reason) {
2329 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)
2330 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)
;
2331
2332 {
2333 MutexAutoLock lock(mMutex);
2334 if (mStopped) {
2335 return;
2336 }
2337 mStopped = true;
2338 }
2339
2340 DoStopSession(reason);
2341}
2342
2343void WebSocketChannel::DoStopSession(nsresult reason) {
2344 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)
2345 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)
;
2346
2347 // normally this should be called on socket thread, but it is ok to call it
2348 // from OnStartRequest before the socket thread machine has gotten underway.
2349 // If mDataStarted is false, this is called on MainThread for Close().
2350 // Otherwise it should be called on the IO thread
2351
2352 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"
, 2352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")"
); do { *((volatile int*)__null) = 2352; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2353 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"
, 2353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted"
")"); do { *((volatile int*)__null) = 2353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2354
2355 if (!mOpenedHttpChannel) {
2356 // The HTTP channel information will never be used in this case
2357 NS_ReleaseOnMainThread("WebSocketChannel::mChannel", mChannel.forget());
2358 NS_ReleaseOnMainThread("WebSocketChannel::mHttpChannel",
2359 mHttpChannel.forget());
2360 NS_ReleaseOnMainThread("WebSocketChannel::mLoadGroup", mLoadGroup.forget());
2361 NS_ReleaseOnMainThread("WebSocketChannel::mCallbacks", mCallbacks.forget());
2362 }
2363
2364 if (mCloseTimer) {
2365 mCloseTimer->Cancel();
2366 mCloseTimer = nullptr;
2367 }
2368
2369 // mOpenTimer must be null if mDataStarted is true and we're not on MainThread
2370 if (mOpenTimer) {
2371 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"
, 2371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
2371; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2372 mOpenTimer->Cancel();
2373 mOpenTimer = nullptr;
2374 }
2375
2376 {
2377 MutexAutoLock lock(mMutex);
2378 if (mReconnectDelayTimer) {
2379 mReconnectDelayTimer->Cancel();
2380 NS_ReleaseOnMainThread("WebSocketChannel::mMutex",
2381 mReconnectDelayTimer.forget());
2382 }
2383 }
2384
2385 if (mPingTimer) {
2386 mPingTimer->Cancel();
2387 mPingTimer = nullptr;
2388 }
2389
2390 if (!mTCPClosed && mDataStarted) {
2391 if (mSocketIn) {
2392 // Drain, within reason, this socket. if we leave any data
2393 // unconsumed (including the tcp fin) a RST will be generated
2394 // The right thing to do here is shutdown(SHUT_WR) and then wait
2395 // a little while to see if any data comes in.. but there is no
2396 // reason to delay things for that when the websocket handshake
2397 // is supposed to guarantee a quiet connection except for that fin.
2398
2399 char buffer[512];
2400 uint32_t count = 0;
2401 uint32_t total = 0;
2402 nsresult rv;
2403 do {
2404 total += count;
2405 rv = mSocketIn->Read(buffer, 512, &count);
2406 if (rv != NS_BASE_STREAM_WOULD_BLOCK && (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || count == 0)) {
2407 mTCPClosed = true;
2408 }
2409 } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && count > 0 && total < 32000);
2410 } else if (mConnection) {
2411 mConnection->DrainSocketData();
2412 }
2413 }
2414
2415 int32_t sessionCount = kLingeringCloseThreshold;
2416 nsWSAdmissionManager::GetSessionCount(sessionCount);
2417
2418 if (!mTCPClosed && (mTransport || mConnection) &&
2419 sessionCount < kLingeringCloseThreshold) {
2420 // 7.1.1 says that the client SHOULD wait for the server to close the TCP
2421 // connection. This is so we can reuse port numbers before 2 MSL expires,
2422 // which is not really as much of a concern for us as the amount of state
2423 // that might be accrued by keeping this channel object around waiting for
2424 // the server. We handle the SHOULD by waiting a short time in the common
2425 // case, but not waiting in the case of high concurrency.
2426 //
2427 // Normally this will be taken care of in AbortSession() after mTCPClosed
2428 // is set when the server close arrives without waiting for the timeout to
2429 // expire.
2430
2431 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)
;
2432
2433 nsresult rv;
2434 rv = NS_NewTimerWithCallback(getter_AddRefs(mLingeringCloseTimer), this,
2435 kLingeringCloseTimeout,
2436 nsITimer::TYPE_ONE_SHOT);
2437 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CleanupConnection();
2438 } else {
2439 CleanupConnection();
2440 }
2441
2442 {
2443 MutexAutoLock lock(mMutex);
2444 if (mCancelable) {
2445 mCancelable->Cancel(NS_ERROR_UNEXPECTED);
2446 mCancelable = nullptr;
2447 }
2448 }
2449
2450 {
2451 MutexAutoLock lock(mCompressorMutex);
2452 mPMCECompressor = nullptr;
2453 }
2454 if (!mCalledOnStop) {
2455 mCalledOnStop = true;
2456
2457 nsWSAdmissionManager::OnStopSession(this, reason);
2458
2459 RefPtr<CallOnStop> runnable = new CallOnStop(this, reason);
2460 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
2461 target->Dispatch(runnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2462 }
2463 }
2464}
2465
2466// Called from MainThread, and called from IOThread in
2467// PrimeNewOutgoingMessage
2468void WebSocketChannel::AbortSession(nsresult reason) {
2469 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)
2470 "] 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)
2471 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)
;
2472
2473 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"
, 2473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))"
") (" "reason must be a failure!" ")"); do { *((volatile int
*)__null) = 2473; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2474
2475 // normally this should be called on socket thread, but it is ok to call it
2476 // from the main thread before StartWebsocketData() has completed
2477 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"
, 2477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || !mDataStarted"
")"); do { *((volatile int*)__null) = 2477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2478
2479 // When we are failing we need to close the TCP connection immediately
2480 // as per 7.1.1
2481 mTCPClosed = true;
2482
2483 if (mLingeringCloseTimer) {
2484 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"
, 2484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") ("
"Lingering without Stop" ")"); do { *((volatile int*)__null)
= 2484; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2485 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)
;
2486 CleanupConnection();
2487 return;
2488 }
2489
2490 {
2491 MutexAutoLock lock(mMutex);
2492 if (mStopped) {
2493 return;
2494 }
2495
2496 if ((mTransport || mConnection) && reason != NS_BASE_STREAM_CLOSED &&
2497 !mRequestedClose && !mClientClosed && !mServerClosed && mDataStarted) {
2498 mRequestedClose = true;
2499 mStopOnClose = reason;
2500 mIOThread->Dispatch(
2501 new OutboundEnqueuer(this,
2502 new OutboundMessage(kMsgTypeFin, VoidCString())),
2503 nsIEventTarget::DISPATCH_NORMAL);
2504 return;
2505 }
2506
2507 mStopped = true;
2508 }
2509
2510 DoStopSession(reason);
2511}
2512
2513// ReleaseSession is called on orderly shutdown
2514void WebSocketChannel::ReleaseSession() {
2515 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)
2516 !!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)
;
2517 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"
, 2517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 2517; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2518
2519 StopSession(NS_OK);
2520}
2521
2522void WebSocketChannel::IncrementSessionCount() {
2523 if (!mIncrementedSessionCount) {
2524 nsWSAdmissionManager::IncrementSessionCount();
2525 mIncrementedSessionCount = true;
2526 }
2527}
2528
2529void WebSocketChannel::DecrementSessionCount() {
2530 // Make sure we decrement session count only once, and only if we incremented
2531 // it. This code is thread-safe: sWebSocketAdmissions->DecrementSessionCount
2532 // is atomic, and mIncrementedSessionCount/mDecrementedSessionCount are set at
2533 // times when they'll never be a race condition for checking/setting them.
2534 if (mIncrementedSessionCount && !mDecrementedSessionCount) {
2535 nsWSAdmissionManager::DecrementSessionCount();
2536 mDecrementedSessionCount = true;
2537 }
2538}
2539
2540namespace {
2541enum ExtensionParseMode { eParseServerSide, eParseClientSide };
2542}
2543
2544static nsresult ParseWebSocketExtension(const nsACString& aExtension,
2545 ExtensionParseMode aMode,
2546 bool& aClientNoContextTakeover,
2547 bool& aServerNoContextTakeover,
2548 int32_t& aClientMaxWindowBits,
2549 int32_t& aServerMaxWindowBits) {
2550 nsCCharSeparatedTokenizer tokens(aExtension, ';');
2551
2552 if (!tokens.hasMoreTokens() ||
2553 !tokens.nextToken().EqualsLiteral("permessage-deflate")) {
2554 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)
2555 ("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)
2556 "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)
2557 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)
;
2558 return NS_ERROR_ILLEGAL_VALUE;
2559 }
2560
2561 aClientNoContextTakeover = aServerNoContextTakeover = false;
2562 aClientMaxWindowBits = aServerMaxWindowBits = -1;
2563
2564 while (tokens.hasMoreTokens()) {
2565 auto token = tokens.nextToken();
2566
2567 int32_t nameEnd, valueStart;
2568 int32_t delimPos = token.FindChar('=');
2569 if (delimPos == kNotFound) {
2570 nameEnd = token.Length();
2571 valueStart = token.Length();
2572 } else {
2573 nameEnd = delimPos;
2574 valueStart = delimPos + 1;
2575 }
2576
2577 auto paramName = Substring(token, 0, nameEnd);
2578 auto paramValue = Substring(token, valueStart);
2579
2580 if (paramName.EqualsLiteral("client_no_context_takeover")) {
2581 if (!paramValue.IsEmpty()) {
2582 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)
2583 ("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)
2584 "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)
2585 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)
;
2586 return NS_ERROR_ILLEGAL_VALUE;
2587 }
2588 if (aClientNoContextTakeover) {
2589 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)
2590 ("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)
2591 "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)
;
2592 return NS_ERROR_ILLEGAL_VALUE;
2593 }
2594 aClientNoContextTakeover = true;
2595 } else if (paramName.EqualsLiteral("server_no_context_takeover")) {
2596 if (!paramValue.IsEmpty()) {
2597 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)
2598 ("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)
2599 "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)
2600 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)
;
2601 return NS_ERROR_ILLEGAL_VALUE;
2602 }
2603 if (aServerNoContextTakeover) {
2604 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)
2605 ("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)
2606 "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)
;
2607 return NS_ERROR_ILLEGAL_VALUE;
2608 }
2609 aServerNoContextTakeover = true;
2610 } else if (paramName.EqualsLiteral("client_max_window_bits")) {
2611 if (aClientMaxWindowBits != -1) {
2612 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)
2613 ("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)
2614 "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)
;
2615 return NS_ERROR_ILLEGAL_VALUE;
2616 }
2617
2618 if (aMode == eParseServerSide && paramValue.IsEmpty()) {
2619 // Use -2 to indicate that "client_max_window_bits" has been parsed,
2620 // but had no value.
2621 aClientMaxWindowBits = -2;
2622 } else {
2623 nsresult errcode;
2624 aClientMaxWindowBits =
2625 PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode);
2626 if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aClientMaxWindowBits < 8 ||
2627 aClientMaxWindowBits > 15) {
2628 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)
2629 ("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)
2630 "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)
2631 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)
;
2632 return NS_ERROR_ILLEGAL_VALUE;
2633 }
2634 }
2635 } else if (paramName.EqualsLiteral("server_max_window_bits")) {
2636 if (aServerMaxWindowBits != -1) {
2637 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)
2638 ("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)
2639 "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)
;
2640 return NS_ERROR_ILLEGAL_VALUE;
2641 }
2642
2643 nsresult errcode;
2644 aServerMaxWindowBits = PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode);
2645 if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aServerMaxWindowBits < 8 ||
2646 aServerMaxWindowBits > 15) {
2647 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)
2648 ("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)
2649 "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)
2650 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)
;
2651 return NS_ERROR_ILLEGAL_VALUE;
2652 }
2653 } else {
2654 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)
2655 ("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)
2656 "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)
2657 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)
;
2658 return NS_ERROR_ILLEGAL_VALUE;
2659 }
2660 }
2661
2662 if (aClientMaxWindowBits == -2) {
2663 aClientMaxWindowBits = -1;
2664 }
2665
2666 return NS_OK;
2667}
2668
2669nsresult WebSocketChannel::HandleExtensions() {
2670 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)
;
2671
2672 nsresult rv;
2673 nsAutoCString extensions;
2674
2675 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"
, 2675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
2675; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2676
2677 rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Extensions"_ns,
Value stored to 'rv' is never read
2678 extensions);
2679 extensions.CompressWhitespace();
2680 if (extensions.IsEmpty()) {
2681 return NS_OK;
2682 }
2683
2684 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)
2685 ("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)
2686 "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)
2687 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)
;
2688
2689 bool clientNoContextTakeover;
2690 bool serverNoContextTakeover;
2691 int32_t clientMaxWindowBits;
2692 int32_t serverMaxWindowBits;
2693
2694 rv = ParseWebSocketExtension(extensions, eParseClientSide,
2695 clientNoContextTakeover, serverNoContextTakeover,
2696 clientMaxWindowBits, serverMaxWindowBits);
2697 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2698 AbortSession(rv);
2699 return rv;
2700 }
2701
2702 if (clientMaxWindowBits == -1) {
2703 clientMaxWindowBits = 15;
2704 }
2705 if (serverMaxWindowBits == -1) {
2706 serverMaxWindowBits = 15;
2707 }
2708
2709 MutexAutoLock lock(mCompressorMutex);
2710 mPMCECompressor = MakeUnique<PMCECompression>(
2711 clientNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits);
2712 if (mPMCECompressor->Active()) {
2713 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)
2714 ("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)
2715 "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)
2716 "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)
2717 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)
2718 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)
;
2719
2720 mNegotiatedExtensions = "permessage-deflate";
2721 } else {
2722 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)
2723 ("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)
2724 "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)
;
2725 mPMCECompressor = nullptr;
2726 AbortSession(NS_ERROR_UNEXPECTED);
2727 return NS_ERROR_UNEXPECTED;
2728 }
2729
2730 return NS_OK;
2731}
2732
2733void ProcessServerWebSocketExtensions(const nsACString& aExtensions,
2734 nsACString& aNegotiatedExtensions) {
2735 aNegotiatedExtensions.Truncate();
2736
2737 for (const auto& ext :
2738 nsCCharSeparatedTokenizer(aExtensions, ',').ToRange()) {
2739 bool clientNoContextTakeover;
2740 bool serverNoContextTakeover;
2741 int32_t clientMaxWindowBits;
2742 int32_t serverMaxWindowBits;
2743
2744 nsresult rv = ParseWebSocketExtension(
2745 ext, eParseServerSide, clientNoContextTakeover, serverNoContextTakeover,
2746 clientMaxWindowBits, serverMaxWindowBits);
2747 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2748 // Ignore extensions that we can't parse
2749 continue;
2750 }
2751
2752 aNegotiatedExtensions.AssignLiteral("permessage-deflate");
2753 if (clientNoContextTakeover) {
2754 aNegotiatedExtensions.AppendLiteral(";client_no_context_takeover");
2755 }
2756 if (serverNoContextTakeover) {
2757 aNegotiatedExtensions.AppendLiteral(";server_no_context_takeover");
2758 }
2759 if (clientMaxWindowBits != -1) {
2760 aNegotiatedExtensions.AppendLiteral(";client_max_window_bits=");
2761 aNegotiatedExtensions.AppendInt(clientMaxWindowBits);
2762 }
2763 if (serverMaxWindowBits != -1) {
2764 aNegotiatedExtensions.AppendLiteral(";server_max_window_bits=");
2765 aNegotiatedExtensions.AppendInt(serverMaxWindowBits);
2766 }
2767
2768 return;
2769 }
2770}
2771
2772nsresult CalculateWebSocketHashedSecret(const nsACString& aKey,
2773 nsACString& aHash) {
2774 nsresult rv;
2775 nsCString key = aKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_ns;
2776 nsCOMPtr<nsICryptoHash> hasher =
2777 do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv);
2778 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"
, 2778); return rv; } } while (false)
;
2779 rv = hasher->Init(nsICryptoHash::SHA1);
2780 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"
, 2780); return rv; } } while (false)
;
2781 rv = hasher->Update((const uint8_t*)key.BeginWriting(), key.Length());
2782 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"
, 2782); return rv; } } while (false)
;
2783 return hasher->Finish(true, aHash);
2784}
2785
2786nsresult WebSocketChannel::SetupRequest() {
2787 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)
;
2788
2789 nsresult rv;
2790
2791 if (mLoadGroup) {
2792 rv = mHttpChannel->SetLoadGroup(mLoadGroup);
2793 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"
, 2793); return rv; } } while (false)
;
2794 }
2795
2796 rv = mHttpChannel->SetLoadFlags(
2797 nsIRequest::LOAD_BACKGROUND | nsIRequest::INHIBIT_CACHING |
2798 nsIRequest::LOAD_BYPASS_CACHE | nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
2799 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"
, 2799); return rv; } } while (false)
;
2800
2801 // we never let websockets be blocked by head CSS/JS loads to avoid
2802 // potential deadlock where server generation of CSS/JS requires
2803 // an XHR signal.
2804 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel));
2805 if (cos) {
2806 cos->AddClassFlags(nsIClassOfService::Unblocked);
2807 }
2808
2809 // draft-ietf-hybi-thewebsocketprotocol-07 illustrates Upgrade: websocket
2810 // in lower case, so go with that. It is technically case insensitive.
2811 rv = mChannel->HTTPUpgrade("websocket"_ns, this);
2812 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"
, 2812); return rv; } } while (false)
;
2813
2814 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Version"_ns,
2815 nsLiteralCString(SEC_WEBSOCKET_VERSION"13"),
2816 false);
2817 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"
, 2817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2818
2819 if (!mOrigin.IsEmpty()) {
2820 rv = mHttpChannel->SetRequestHeader("Origin"_ns, mOrigin, false);
2821 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"
, 2821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2821; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2822 }
2823
2824 if (!mProtocol.IsEmpty()) {
2825 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Protocol"_ns, mProtocol,
2826 true);
2827 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"
, 2827); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2827; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2828 }
2829
2830 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Extensions"_ns,
2831 "permessage-deflate"_ns, false);
2832 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"
, 2832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2832; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2833
2834 uint8_t* secKey;
2835 nsAutoCString secKeyString;
2836
2837 rv = mRandomGenerator->GenerateRandomBytes(16, &secKey);
2838 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"
, 2838); return rv; } } while (false)
;
2839 rv = Base64Encode(reinterpret_cast<const char*>(secKey), 16, secKeyString);
2840 free(secKey);
2841 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2842 return rv;
2843 }
2844
2845 rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Key"_ns, secKeyString,
2846 false);
2847 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"
, 2847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2848 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)
;
2849
2850 // prepare the value we expect to see in
2851 // the sec-websocket-accept response header
2852 rv = CalculateWebSocketHashedSecret(secKeyString, mHashedSecret);
2853 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"
, 2853); return rv; } } while (false)
;
2854 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)
2855 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)
;
2856
2857 mHttpChannelId = mHttpChannel->ChannelId();
2858
2859 return NS_OK;
2860}
2861
2862nsresult WebSocketChannel::DoAdmissionDNS() {
2863 nsresult rv;
2864
2865 nsCString hostName;
2866 rv = mURI->GetHost(hostName);
2867 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"
, 2867); return rv; } } while (false)
;
2868 mAddress = hostName;
2869 nsCString path;
2870 rv = mURI->GetFilePath(path);
2871 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"
, 2871); return rv; } } while (false)
;
2872 mPath = path;
2873 rv = mURI->GetPort(&mPort);
2874 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"
, 2874); return rv; } } while (false)
;
2875 if (mPort == -1) mPort = (mEncrypted ? kDefaultWSSPort : kDefaultWSPort);
2876 nsCOMPtr<nsIDNSService> dns;
2877 dns = mozilla::components::DNS::Service(&rv);
2878 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"
, 2878); return rv; } } while (false)
;
2879 nsCOMPtr<nsIEventTarget> main = GetMainThreadSerialEventTarget();
2880 nsCOMPtr<nsICancelable> cancelable;
2881 rv = dns->AsyncResolveNative(hostName, nsIDNSService::RESOLVE_TYPE_DEFAULT,
2882 nsIDNSService::RESOLVE_DEFAULT_FLAGS, nullptr,
2883 this, main, mLoadInfo->GetOriginAttributes(),
2884 getter_AddRefs(cancelable));
2885 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2886 return rv;
2887 }
2888
2889 MutexAutoLock lock(mMutex);
2890 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"
, 2890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable"
")"); do { *((volatile int*)__null) = 2890; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2891 mCancelable = std::move(cancelable);
2892 return rv;
2893}
2894
2895nsresult WebSocketChannel::ApplyForAdmission() {
2896 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)
;
2897
2898 // Websockets has a policy of 1 session at a time being allowed in the
2899 // CONNECTING state per server IP address (not hostname)
2900
2901 // Check to see if a proxy is being used before making DNS call
2902 nsCOMPtr<nsIProtocolProxyService> pps;
2903 pps = mozilla::components::ProtocolProxy::Service();
2904
2905 if (!pps) {
2906 // go straight to DNS
2907 // expect the callback in ::OnLookupComplete
2908 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)
2909 "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)
;
2910 return DoAdmissionDNS();
2911 }
2912
2913 nsresult rv;
2914 nsCOMPtr<nsICancelable> cancelable;
2915 rv = pps->AsyncResolve(
2916 mHttpChannel,
2917 nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY |
2918 nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
2919 nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
2920 this, nullptr, getter_AddRefs(cancelable));
2921
2922 MutexAutoLock lock(mMutex);
2923 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"
, 2923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable"
")"); do { *((volatile int*)__null) = 2923; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2924 mCancelable = std::move(cancelable);
2925 return rv;
2926}
2927
2928// Called after both OnStartRequest and OnTransportAvailable have
2929// executed. This essentially ends the handshake and starts the websockets
2930// protocol state machine.
2931nsresult WebSocketChannel::CallStartWebsocketData() {
2932 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)
;
2933 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"
, 2933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
2933; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2934
2935 if (mOpenTimer) {
2936 mOpenTimer->Cancel();
2937 mOpenTimer = nullptr;
2938 }
2939
2940 nsCOMPtr<nsIEventTarget> target = GetTargetThread();
2941 if (target && !target->IsOnCurrentThread()) {
2942 return target->Dispatch(
2943 NewRunnableMethod("net::WebSocketChannel::StartWebsocketData", this,
2944 &WebSocketChannel::StartWebsocketData),
2945 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2946 }
2947
2948 return StartWebsocketData();
2949}
2950
2951nsresult WebSocketChannel::StartWebsocketData() {
2952 {
2953 MutexAutoLock lock(mMutex);
2954 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)
;
2955 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"
, 2955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDataStarted"
") (" "StartWebsocketData twice" ")"); do { *((volatile int*
)__null) = 2955; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2956
2957 if (mStopped) {
2958 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)
2959 ("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)
2960 "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)
;
2961 return NS_ERROR_NOT_AVAILABLE;
2962 }
2963 }
2964
2965 RefPtr<WebSocketChannel> self = this;
2966 mIOThread->Dispatch(NS_NewRunnableFunction(
2967 "WebSocketChannel::StartWebsocketData", [self{std::move(self)}] {
2968 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)
;
2969
2970 NS_DispatchToMainThread(
2971 NewRunnableMethod("net::WebSocketChannel::NotifyOnStart", self,
2972 &WebSocketChannel::NotifyOnStart),
2973 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2974
2975 nsresult rv = self->mConnection ? self->mConnection->StartReading()
2976 : self->mSocketIn->AsyncWait(
2977 self, 0, 0, self->mIOThread);
2978 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2979 self->AbortSession(rv);
2980 }
2981
2982 if (self->mPingInterval) {
2983 rv = self->StartPinging();
2984 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2985 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)
2986 "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)
2987 "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)
2988 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)
;
2989 self->AbortSession(rv);
2990 }
2991 }
2992 }));
2993
2994 return NS_OK;
2995}
2996
2997void WebSocketChannel::NotifyOnStart() {
2998 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)
2999 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)
;
3000 mDataStarted = true;
3001 if (mListenerMT) {
3002 nsresult rv = mListenerMT->mListener->OnStart(mListenerMT->mContext);
3003 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3004 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)
3005 ("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)
3006 "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)
3007 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)
;
3008 }
3009 }
3010}
3011
3012nsresult WebSocketChannel::StartPinging() {
3013 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)
;
3014 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"
, 3014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 3014; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3015 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"
, 3015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval"
")"); do { *((volatile int*)__null) = 3015; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3016 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"
, 3016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPingTimer"
")"); do { *((volatile int*)__null) = 3016; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3017
3018 nsresult rv;
3019 rv = NS_NewTimerWithCallback(getter_AddRefs(mPingTimer), this, mPingInterval,
3020 nsITimer::TYPE_ONE_SHOT);
3021 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3022 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)
3023 (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)
;
3024 } else {
3025 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"
, 3025)
;
3026 }
3027
3028 return NS_OK;
3029}
3030
3031void WebSocketChannel::ReportConnectionTelemetry(nsresult aStatusCode) {
3032 // 3 bits are used. high bit is for wss, middle bit for failed,
3033 // and low bit for proxy..
3034 // 0 - 7 : ws-ok-plain, ws-ok-proxy, ws-failed-plain, ws-failed-proxy,
3035 // wss-ok-plain, wss-ok-proxy, wss-failed-plain, wss-failed-proxy
3036
3037 bool didProxy = false;
3038
3039 nsCOMPtr<nsIProxyInfo> pi;
3040 nsCOMPtr<nsIProxiedChannel> pc = do_QueryInterface(mChannel);
3041 if (pc) pc->GetProxyInfo(getter_AddRefs(pi));
3042 if (pi) {
3043 nsAutoCString proxyType;
3044 pi->GetType(proxyType);
3045 if (!proxyType.IsEmpty() && !proxyType.EqualsLiteral("direct")) {
3046 didProxy = true;
3047 }
3048 }
3049
3050 uint8_t value =
3051 (mEncrypted ? (1 << 2) : 0) |
3052 (!(mGotUpgradeOK && NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1)
))
) ? (1 << 1) : 0) |
3053 (didProxy ? (1 << 0) : 0);
3054
3055 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)
;
3056 Telemetry::Accumulate(Telemetry::WEBSOCKETS_HANDSHAKE_TYPE, value);
3057}
3058
3059// nsIDNSListener
3060
3061NS_IMETHODIMPnsresult
3062WebSocketChannel::OnLookupComplete(nsICancelable* aRequest,
3063 nsIDNSRecord* aRecord, nsresult aStatus) {
3064 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)
3065 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)
;
3066
3067 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"
, 3067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3067; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3068
3069 {
3070 MutexAutoLock lock(mMutex);
3071 mCancelable = nullptr;
3072 }
3073
3074 if (mStopped) {
3075 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)
;
3076 return NS_OK;
3077 }
3078
3079 // These failures are not fatal - we just use the hostname as the key
3080 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
3081 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)
;
3082
3083 // set host in case we got here without calling DoAdmissionDNS()
3084 mURI->GetHost(mAddress);
3085 } else {
3086 nsCOMPtr<nsIDNSAddrRecord> record = do_QueryInterface(aRecord);
3087 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"
, 3087); AnnotateMozCrashReason("MOZ_ASSERT" "(" "record" ")"
); do { *((volatile int*)__null) = 3087; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3088 nsresult rv = record->GetNextAddrAsString(mAddress);
3089 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3090 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)
;
3091 }
3092 }
3093
3094 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)
;
3095 nsWSAdmissionManager::ConditionallyConnect(this);
3096
3097 return NS_OK;
3098}
3099
3100// nsIProtocolProxyCallback
3101NS_IMETHODIMPnsresult
3102WebSocketChannel::OnProxyAvailable(nsICancelable* aRequest,
3103 nsIChannel* aChannel, nsIProxyInfo* pi,
3104 nsresult status) {
3105 {
3106 MutexAutoLock lock(mMutex);
3107 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"
, 3107); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable || (aRequest == mCancelable)"
")"); do { *((volatile int*)__null) = 3107; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3108 mCancelable = nullptr;
3109 }
3110
3111 if (mStopped) {
3112 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)
3113 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)
;
3114 return NS_OK;
3115 }
3116
3117 nsAutoCString type;
3118 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)))
&&
3119 !type.EqualsLiteral("direct")) {
3120 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)
3121 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)
;
3122 // call DNS callback directly without DNS resolver
3123 OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE);
3124 } else {
3125 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)
3126 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)
;
3127 nsresult rv = DoAdmissionDNS();
3128 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3129 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)
;
3130 // call DNS callback directly without DNS resolver
3131 OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE);
3132 }
3133 }
3134
3135 // notify listener of OnProxyAvailable
3136 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)
3137 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)
;
3138 nsresult rv;
3139 nsCOMPtr<nsIProtocolProxyCallback> ppc(
3140 do_QueryInterface(mListenerMT->mListener, &rv));
3141 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3142 rv = ppc->OnProxyAvailable(aRequest, aChannel, pi, status);
3143 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3144 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)
3145 ("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)
3146 " 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)
3147 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)
;
3148 }
3149 }
3150
3151 return NS_OK;
3152}
3153
3154// nsIInterfaceRequestor
3155
3156NS_IMETHODIMPnsresult
3157WebSocketChannel::GetInterface(const nsIID& iid, void** result) {
3158 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)
;
3159
3160 if (iid.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::COMTypeInfo<nsIChannelEventSink, void
>::kIID)
)) {
3161 return QueryInterface(iid, result);
3162 }
3163
3164 if (mCallbacks) return mCallbacks->GetInterface(iid, result);
3165
3166 return NS_ERROR_NO_INTERFACE;
3167}
3168
3169// nsIChannelEventSink
3170
3171NS_IMETHODIMPnsresult
3172WebSocketChannel::AsyncOnChannelRedirect(
3173 nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t flags,
3174 nsIAsyncVerifyRedirectCallback* callback) {
3175 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)
;
3176
3177 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"
, 3177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3177; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3178
3179 nsresult rv;
3180
3181 nsCOMPtr<nsIURI> newuri;
3182 rv = newChannel->GetURI(getter_AddRefs(newuri));
3183 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"
, 3183); return rv; } } while (false)
;
3184
3185 // newuri is expected to be http or https
3186 bool newuriIsHttps = newuri->SchemeIs("https");
3187
3188 // allow insecure->secure redirects for HTTP Strict Transport Security (from
3189 // ws://FOO to https://FOO (mapped to wss://FOO)
3190 if (!(flags & (nsIChannelEventSink::REDIRECT_INTERNAL |
3191 nsIChannelEventSink::REDIRECT_STS_UPGRADE))) {
3192 nsAutoCString newSpec;
3193 rv = newuri->GetSpec(newSpec);
3194 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"
, 3194); return rv; } } while (false)
;
3195
3196 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)
3197 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)
;
3198 return NS_ERROR_FAILURE;
3199 }
3200
3201 if (mEncrypted && !newuriIsHttps) {
3202 nsAutoCString spec;
3203 if (NS_SUCCEEDED(newuri->GetSpec(spec))((bool)(__builtin_expect(!!(!NS_FAILED_impl(newuri->GetSpec
(spec))), 1)))
) {
3204 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)
3205 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)
;
3206 }
3207 return NS_ERROR_FAILURE;
3208 }
3209
3210 nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(newChannel, &rv);
3211 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3212 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)
;
3213 return rv;
3214 }
3215
3216 nsCOMPtr<nsIHttpChannelInternal> newUpgradeChannel =
3217 do_QueryInterface(newChannel, &rv);
3218
3219 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3220 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)
;
3221 return rv;
3222 }
3223
3224 // The redirect is likely OK
3225
3226 newChannel->SetNotificationCallbacks(this);
3227
3228 mEncrypted = newuriIsHttps;
3229 rv = NS_MutateURI(newuri)
3230 .SetScheme(mEncrypted ? "wss"_ns : "ws"_ns)
3231 .Finalize(mURI);
3232
3233 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3234 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)
;
3235 return rv;
3236 }
3237
3238 mHttpChannel = newHttpChannel;
3239 mChannel = newUpgradeChannel;
3240 rv = SetupRequest();
3241 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3242 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)
;
3243 return rv;
3244 }
3245
3246 // Redirected-to URI may need to be delayed by 1-connecting-per-host and
3247 // delay-after-fail algorithms. So hold off calling OnRedirectVerifyCallback
3248 // until BeginOpen, when we know it's OK to proceed with new channel.
3249 mRedirectCallback = callback;
3250
3251 // Mark old channel as successfully connected so we'll clear any FailDelay
3252 // associated with the old URI. Note: no need to also call OnStopSession:
3253 // it's a no-op for successful, already-connected channels.
3254 nsWSAdmissionManager::OnConnected(this);
3255
3256 // ApplyForAdmission as if we were starting from fresh...
3257 mAddress.Truncate();
3258 mOpenedHttpChannel = false;
3259 rv = ApplyForAdmission();
3260 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3261 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)
;
3262 mRedirectCallback = nullptr;
3263 return rv;
3264 }
3265
3266 return NS_OK;
3267}
3268
3269// nsITimerCallback
3270
3271NS_IMETHODIMPnsresult
3272WebSocketChannel::Notify(nsITimer* timer) {
3273 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)
;
3274
3275 if (timer == mCloseTimer) {
3276 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"
, 3276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientClosed"
") (" "Close Timeout without local close" ")"); do { *((volatile
int*)__null) = 3276; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3277 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"
, 3277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 3277; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3278
3279 mCloseTimer = nullptr;
3280 if (mStopped || mServerClosed) { /* no longer relevant */
3281 return NS_OK;
3282 }
3283
3284 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)
;
3285 AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL);
3286 } else if (timer == mOpenTimer) {
3287 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"
, 3287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3287; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3288
3289 mOpenTimer = nullptr;
3290 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)
;
3291 if (mStopped || mServerClosed) { /* no longer relevant */
3292 return NS_OK;
3293 }
3294
3295 AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL);
3296 MOZ_PUSH_IGNORE_THREAD_SAFETYGCC diagnostic push GCC diagnostic ignored "-Wthread-safety"
3297 // mReconnectDelayTimer is only modified on MainThread, we can read it
3298 // without a lock, but ONLY if we're on MainThread! And if we're not
3299 // on MainThread, it can't be mReconnectDelayTimer
3300 } else if (NS_IsMainThread() && timer == mReconnectDelayTimer) {
3301 MOZ_POP_THREAD_SAFETYGCC diagnostic pop
3302 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"
, 3303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED"
") (" "woke up from delay w/o being delayed?" ")"); do { *((
volatile int*)__null) = 3303; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
3303 "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"
, 3303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED"
") (" "woke up from delay w/o being delayed?" ")"); do { *((
volatile int*)__null) = 3303; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
3304
3305 {
3306 MutexAutoLock lock(mMutex);
3307 mReconnectDelayTimer = nullptr;
3308 }
3309 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)
;
3310 BeginOpen(false);
3311 } else if (timer == mPingTimer) {
3312 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"
, 3312); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 3312; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3313
3314 if (mClientClosed || mServerClosed || mRequestedClose) {
3315 // no point in worrying about ping now
3316 mPingTimer = nullptr;
3317 return NS_OK;
3318 }
3319
3320 if (!mPingOutstanding) {
3321 // Ping interval must be non-null or PING was forced by OnNetworkChanged()
3322 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"
, 3322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval || mPingForced"
")"); do { *((volatile int*)__null) = 3322; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3323 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)
;
3324 mPingOutstanding = 1;
3325 mPingForced = false;
3326 mPingTimer->InitWithCallback(this, mPingResponseTimeout,
3327 nsITimer::TYPE_ONE_SHOT);
3328 GeneratePing();
3329 } else {
3330 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)
;
3331 mPingTimer = nullptr;
3332 AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL);
3333 }
3334 } else if (timer == mLingeringCloseTimer) {
3335 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)
;
3336 CleanupConnection();
3337 } else {
3338 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"
, 3338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ") (" "Unknown Timer"
")"); do { *((volatile int*)__null) = 3338; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3339 }
3340
3341 return NS_OK;
3342}
3343
3344// nsINamed
3345
3346NS_IMETHODIMPnsresult
3347WebSocketChannel::GetName(nsACString& aName) {
3348 aName.AssignLiteral("WebSocketChannel");
3349 return NS_OK;
3350}
3351
3352// nsIWebSocketChannel
3353
3354NS_IMETHODIMPnsresult
3355WebSocketChannel::GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) {
3356 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)
;
3357 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"
, 3357); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3357; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3358
3359 *aSecurityInfo = nullptr;
3360
3361 if (mConnection) {
3362 nsresult rv = mConnection->GetSecurityInfo(aSecurityInfo);
3363 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3364 return rv;
3365 }
3366 return NS_OK;
3367 }
3368
3369 if (mTransport) {
3370 nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
3371 nsresult rv =
3372 mTransport->GetTlsSocketControl(getter_AddRefs(tlsSocketControl));
3373 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3374 return rv;
3375 }
3376 nsCOMPtr<nsITransportSecurityInfo> securityInfo(
3377 do_QueryInterface(tlsSocketControl));
3378 if (securityInfo) {
3379 securityInfo.forget(aSecurityInfo);
3380 }
3381 }
3382 return NS_OK;
3383}
3384
3385NS_IMETHODIMPnsresult
3386WebSocketChannel::AsyncOpen(nsIURI* aURI, const nsACString& aOrigin,
3387 JS::Handle<JS::Value> aOriginAttributes,
3388 uint64_t aInnerWindowID,
3389 nsIWebSocketListener* aListener,
3390 nsISupports* aContext, JSContext* aCx) {
3391 OriginAttributes attrs;
3392 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
3393 return NS_ERROR_INVALID_ARG;
3394 }
3395 return AsyncOpenNative(aURI, aOrigin, attrs, aInnerWindowID, aListener,
3396 aContext);
3397}
3398
3399NS_IMETHODIMPnsresult
3400WebSocketChannel::AsyncOpenNative(nsIURI* aURI, const nsACString& aOrigin,
3401 const OriginAttributes& aOriginAttributes,
3402 uint64_t aInnerWindowID,
3403 nsIWebSocketListener* aListener,
3404 nsISupports* aContext) {
3405 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)
;
3406
3407 aOriginAttributes.CreateSuffix(mOriginSuffix);
3408
3409 if (!NS_IsMainThread()) {
3410 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"
, 3410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"not main thread" ")"); do { *((volatile int*)__null) = 3410
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3411 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)
;
3412 return NS_ERROR_UNEXPECTED;
3413 }
3414
3415 if ((!aURI && !mIsServerSide) || !aListener) {
3416 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)
;
3417 return NS_ERROR_UNEXPECTED;
3418 }
3419
3420 if (mListenerMT || mWasOpened) return NS_ERROR_ALREADY_OPENED;
3421
3422 nsresult rv;
3423
3424 // Ensure target thread is set if RetargetDeliveryTo isn't called
3425 {
3426 auto lock = mTargetThread.Lock();
3427 if (!lock.ref()) {
3428 lock.ref() = GetMainThreadSerialEventTarget();
3429 }
3430 }
3431
3432 mIOThread = mozilla::components::SocketTransport::Service(&rv);
3433 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3434 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"
, 3434)
;
3435 return rv;
3436 }
3437
3438 nsCOMPtr<nsIPrefBranch> prefService;
3439 prefService = mozilla::components::Preferences::Service();
3440
3441 if (prefService) {
3442 int32_t intpref;
3443 rv =
3444 prefService->GetIntPref("network.websocket.max-message-size", &intpref);
3445 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3446 mMaxMessageSize = clamped(intpref, 1024, INT32_MAX(2147483647));
3447 }
3448 rv = prefService->GetIntPref("network.websocket.timeout.close", &intpref);
3449 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3450 mCloseTimeout = clamped(intpref, 1, 1800) * 1000;
3451 }
3452 rv = prefService->GetIntPref("network.websocket.timeout.open", &intpref);
3453 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3454 mOpenTimeout = clamped(intpref, 1, 1800) * 1000;
3455 }
3456 rv = prefService->GetIntPref("network.websocket.timeout.ping.request",
3457 &intpref);
3458 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingInterval) {
3459 mPingInterval = clamped(intpref, 0, 86400) * 1000;
3460 }
3461 rv = prefService->GetIntPref("network.websocket.timeout.ping.response",
3462 &intpref);
3463 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingTimeout) {
3464 mPingResponseTimeout = clamped(intpref, 1, 3600) * 1000;
3465 }
3466 rv = prefService->GetIntPref("network.websocket.max-connections", &intpref);
3467 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3468 mMaxConcurrentConnections = clamped(intpref, 1, 0xffff);
3469 }
3470 }
3471
3472 int32_t sessionCount = -1;
3473 nsWSAdmissionManager::GetSessionCount(sessionCount);
3474 if (sessionCount >= 0) {
3475 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)
3476 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)
;
3477 }
3478
3479 if (sessionCount >= mMaxConcurrentConnections) {
3480 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)
3481 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)
;
3482
3483 // WebSocket connections are expected to be long lived, so return
3484 // an error here instead of queueing
3485 return NS_ERROR_SOCKET_CREATE_FAILED;
3486 }
3487
3488 mInnerWindowID = aInnerWindowID;
3489 mOriginalURI = aURI;
3490 mURI = mOriginalURI;
3491 mOrigin = aOrigin;
3492
3493 if (mIsServerSide) {
3494 // IncrementSessionCount();
3495 mWasOpened = 1;
3496 mListenerMT = new ListenerAndContextContainer(aListener, aContext);
3497 rv = mServerTransportProvider->SetListener(this);
3498 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"
, 3498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 3498; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3499 mServerTransportProvider = nullptr;
3500
3501 return NS_OK;
3502 }
3503
3504 mURI->GetHostPort(mHost);
3505
3506 mRandomGenerator = mozilla::components::RandomGenerator::Service(&rv);
3507 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3508 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"
, 3508)
;
3509 return rv;
3510 }
3511
3512 nsCOMPtr<nsIURI> localURI;
3513 nsCOMPtr<nsIChannel> localChannel;
3514
3515 rv = NS_MutateURI(mURI)
3516 .SetScheme(mEncrypted ? "https"_ns : "http"_ns)
3517 .Finalize(localURI);
3518 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"
, 3518); return rv; } } while (false)
;
3519
3520 nsCOMPtr<nsIIOService> ioService;
3521 ioService = mozilla::components::IO::Service(&rv);
3522 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3523 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"
, 3523)
;
3524 return rv;
3525 }
3526
3527 // Ideally we'd call newChannelFromURIWithLoadInfo here, but that doesn't
3528 // allow setting proxy uri/flags
3529 rv = ioService->NewChannelFromURIWithProxyFlags(
3530 localURI, mURI,
3531 nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY |
3532 nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
3533 nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
3534 mLoadInfo->LoadingNode(), mLoadInfo->GetLoadingPrincipal(),
3535 mLoadInfo->TriggeringPrincipal(), mLoadInfo->GetSecurityFlags(),
3536 mLoadInfo->InternalContentPolicyType(), getter_AddRefs(localChannel));
3537 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"
, 3537); return rv; } } while (false)
;
3538
3539 // Please note that we still call SetLoadInfo on the channel because
3540 // we want the same instance of the loadInfo to be set on the channel.
3541 rv = localChannel->SetLoadInfo(mLoadInfo);
3542 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"
, 3542); return rv; } } while (false)
;
3543
3544 // Pass most GetInterface() requests through to our instantiator, but handle
3545 // nsIChannelEventSink in this object in order to deal with redirects
3546 localChannel->SetNotificationCallbacks(this);
3547
3548 class MOZ_STACK_CLASS CleanUpOnFailure {
3549 public:
3550 explicit CleanUpOnFailure(WebSocketChannel* aWebSocketChannel)
3551 : mWebSocketChannel(aWebSocketChannel) {}
3552
3553 ~CleanUpOnFailure() {
3554 if (!mWebSocketChannel->mWasOpened) {
3555 mWebSocketChannel->mChannel = nullptr;
3556 mWebSocketChannel->mHttpChannel = nullptr;
3557 }
3558 }
3559
3560 WebSocketChannel* mWebSocketChannel;
3561 };
3562
3563 CleanUpOnFailure cuof(this);
3564
3565 mChannel = do_QueryInterface(localChannel, &rv);
3566 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"
, 3566); return rv; } } while (false)
;
3567
3568 mHttpChannel = do_QueryInterface(localChannel, &rv);
3569 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"
, 3569); return rv; } } while (false)
;
3570
3571 rv = SetupRequest();
3572 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3573
3574 mPrivateBrowsing = NS_UsePrivateBrowsing(localChannel);
3575
3576 if (mConnectionLogService && !mPrivateBrowsing) {
3577 mConnectionLogService->AddHost(mHost, mSerial,
3578 BaseWebSocketChannel::mEncrypted);
3579 }
3580
3581 rv = ApplyForAdmission();
3582 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3583
3584 // Register for prefs change notifications
3585 nsCOMPtr<nsIObserverService> observerService =
3586 mozilla::services::GetObserverService();
3587 if (!observerService) {
3588 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"
, 3588)
;
3589 return NS_ERROR_FAILURE;
3590 }
3591
3592 rv = observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC"network:link-status-changed", false);
3593 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"
, 3593)
) {
3594 return rv;
3595 }
3596
3597 // Only set these if the open was successful:
3598 //
3599 mWasOpened = 1;
3600 mListenerMT = new ListenerAndContextContainer(aListener, aContext);
3601 IncrementSessionCount();
3602
3603 return rv;
3604}
3605
3606NS_IMETHODIMPnsresult
3607WebSocketChannel::Close(uint16_t code, const nsACString& reason) {
3608 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)
;
3609 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"
, 3609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3609; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3610
3611 {
3612 MutexAutoLock lock(mMutex);
3613
3614 if (mRequestedClose) {
3615 return NS_OK;
3616 }
3617
3618 if (mStopped) {
3619 return NS_ERROR_NOT_AVAILABLE;
3620 }
3621
3622 // The API requires the UTF-8 string to be 123 or less bytes
3623 if (reason.Length() > 123) return NS_ERROR_ILLEGAL_VALUE;
3624
3625 mRequestedClose = true;
3626 mScriptCloseReason = reason;
3627 mScriptCloseCode = code;
3628
3629 if (mDataStarted) {
3630 return mIOThread->Dispatch(
3631 new OutboundEnqueuer(this,
3632 new OutboundMessage(kMsgTypeFin, VoidCString())),
3633 nsIEventTarget::DISPATCH_NORMAL);
3634 }
3635
3636 mStopped = true;
3637 }
3638
3639 nsresult rv;
3640 if (code == CLOSE_GOING_AWAY) {
3641 // Not an error: for example, tab has closed or navigated away
3642 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)
;
3643 rv = NS_OK;
3644 } else {
3645 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)
;
3646 rv = NS_ERROR_NOT_CONNECTED;
3647 }
3648
3649 DoStopSession(rv);
3650 return rv;
3651}
3652
3653NS_IMETHODIMPnsresult
3654WebSocketChannel::SendMsg(const nsACString& aMsg) {
3655 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)
;
3656
3657 return SendMsgCommon(aMsg, false, aMsg.Length());
3658}
3659
3660NS_IMETHODIMPnsresult
3661WebSocketChannel::SendBinaryMsg(const nsACString& aMsg) {
3662 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)
;
3663 return SendMsgCommon(aMsg, true, aMsg.Length());
3664}
3665
3666NS_IMETHODIMPnsresult
3667WebSocketChannel::SendBinaryStream(nsIInputStream* aStream, uint32_t aLength) {
3668 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)
;
3669
3670 return SendMsgCommon(VoidCString(), true, aLength, aStream);
3671}
3672
3673nsresult WebSocketChannel::SendMsgCommon(const nsACString& aMsg, bool aIsBinary,
3674 uint32_t aLength,
3675 nsIInputStream* aStream) {
3676 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"
, 3676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnTargetThread()"
") (" "not target thread" ")"); do { *((volatile int*)__null
) = 3676; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3677
3678 if (!mDataStarted) {
3679 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)
;
3680 return NS_ERROR_UNEXPECTED;
3681 }
3682
3683 if (mRequestedClose) {
3684 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)
;
3685 return NS_ERROR_UNEXPECTED;
3686 }
3687
3688 if (mStopped) {
3689 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)
;
3690 return NS_ERROR_NOT_CONNECTED;
3691 }
3692
3693 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"
, 3693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMaxMessageSize >= 0"
") (" "max message size negative" ")"); do { *((volatile int
*)__null) = 3693; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3694 if (aLength > static_cast<uint32_t>(mMaxMessageSize)) {
3695 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)
;
3696 return NS_ERROR_FILE_TOO_BIG;
3697 }
3698
3699 if (mConnectionLogService && !mPrivateBrowsing) {
3700 mConnectionLogService->NewMsgSent(mHost, mSerial, aLength);
3701 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)
;
3702 }
3703
3704 return mIOThread->Dispatch(
3705 aStream
3706 ? new OutboundEnqueuer(this, new OutboundMessage(aStream, aLength))
3707 : new OutboundEnqueuer(
3708 this,
3709 new OutboundMessage(
3710 aIsBinary ? kMsgTypeBinaryString : kMsgTypeString, aMsg)),
3711 nsIEventTarget::DISPATCH_NORMAL);
3712}
3713
3714// nsIHttpUpgradeListener
3715
3716NS_IMETHODIMPnsresult
3717WebSocketChannel::OnTransportAvailable(nsISocketTransport* aTransport,
3718 nsIAsyncInputStream* aSocketIn,
3719 nsIAsyncOutputStream* aSocketOut) {
3720 if (!NS_IsMainThread()) {
3721 return NS_DispatchToMainThread(
3722 new CallOnTransportAvailable(this, aTransport, aSocketIn, aSocketOut));
3723 }
3724
3725 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)
3726 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)
;
3727
3728 if (mStopped) {
3729 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)
;
3730 return NS_OK;
3731 }
3732
3733 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"
, 3733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3733; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3734 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"
, 3734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OTA duplicated" ")"); do { *((volatile int*)__null) =
3734; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3735 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"
, 3735); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSocketIn" ") ("
"OTA with invalid socketIn" ")"); do { *((volatile int*)__null
) = 3735; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3736
3737 mTransport = aTransport;
3738 mSocketIn = aSocketIn;
3739 mSocketOut = aSocketOut;
3740
3741 nsresult rv;
3742 rv = mTransport->SetEventSink(nullptr, nullptr);
3743 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3744 rv = mTransport->SetSecurityCallbacks(this);
3745 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3746
3747 return OnTransportAvailableInternal();
3748}
3749
3750NS_IMETHODIMPnsresult
3751WebSocketChannel::OnWebSocketConnectionAvailable(
3752 WebSocketConnectionBase* aConnection) {
3753 if (!NS_IsMainThread()) {
3754 RefPtr<WebSocketChannel> self = this;
3755 RefPtr<WebSocketConnectionBase> connection = aConnection;
3756 return NS_DispatchToMainThread(NS_NewRunnableFunction(
3757 "WebSocketChannel::OnWebSocketConnectionAvailable",
3758 [self, connection]() {
3759 self->OnWebSocketConnectionAvailable(connection);
3760 }));
3761 }
3762
3763 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)
3764 ("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)
3765 "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)
3766 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)
;
3767
3768 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"
, 3768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3768; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3769 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"
, 3770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3770; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3770 "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"
, 3770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3770; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3771 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"
, 3771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aConnection"
")"); do { *((volatile int*)__null) = 3771; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3772
3773 if (mStopped) {
3774 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)
;
3775 aConnection->Close();
3776 return NS_OK;
3777 }
3778
3779 nsresult rv = aConnection->Init(this);
3780 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3781 return rv;
3782 }
3783
3784 mConnection = aConnection;
3785 // Note: mIOThread will be IPDL background thread.
3786 mConnection->GetIoTarget(getter_AddRefs(mIOThread));
3787 return OnTransportAvailableInternal();
3788}
3789
3790nsresult WebSocketChannel::OnTransportAvailableInternal() {
3791 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"
, 3791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3791; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3792 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"
, 3793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3793; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3793 "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"
, 3793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OnWebSocketConnectionAvailable duplicated" ")"); do {
*((volatile int*)__null) = 3793; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3794 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"
, 3794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSocketIn || mConnection"
")"); do { *((volatile int*)__null) = 3794; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3795
3796 mRecvdHttpUpgradeTransport = 1;
3797 if (mGotUpgradeOK) {
3798 // We're now done CONNECTING, which means we can now open another,
3799 // perhaps parallel, connection to the same host if one
3800 // is pending
3801 nsWSAdmissionManager::OnConnected(this);
3802
3803 return CallStartWebsocketData();
3804 }
3805
3806 if (mIsServerSide) {
3807 if (!mNegotiatedExtensions.IsEmpty()) {
3808 bool clientNoContextTakeover;
3809 bool serverNoContextTakeover;
3810 int32_t clientMaxWindowBits;
3811 int32_t serverMaxWindowBits;
3812
3813 nsresult rv = ParseWebSocketExtension(
3814 mNegotiatedExtensions, eParseServerSide, clientNoContextTakeover,
3815 serverNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits);
3816 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"
, 3816); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "illegal value provided by server" ")"); do { *((volatile
int*)__null) = 3816; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3817
3818 if (clientMaxWindowBits == -1) {
3819 clientMaxWindowBits = 15;
3820 }
3821 if (serverMaxWindowBits == -1) {
3822 serverMaxWindowBits = 15;
3823 }
3824
3825 MutexAutoLock lock(mCompressorMutex);
3826 mPMCECompressor = MakeUnique<PMCECompression>(
3827 serverNoContextTakeover, serverMaxWindowBits, clientMaxWindowBits);
3828 if (mPMCECompressor->Active()) {
3829 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)
3830 ("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)
3831 "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)
3832 "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)
3833 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)
3834 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)
;
3835
3836 mNegotiatedExtensions = "permessage-deflate";
3837 } else {
3838 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)
3839 ("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)
3840 "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)
;
3841 mPMCECompressor = nullptr;
3842 AbortSession(NS_ERROR_UNEXPECTED);
3843 return NS_ERROR_UNEXPECTED;
3844 }
3845 }
3846
3847 return CallStartWebsocketData();
3848 }
3849
3850 return NS_OK;
3851}
3852
3853NS_IMETHODIMPnsresult
3854WebSocketChannel::OnUpgradeFailed(nsresult aErrorCode) {
3855 // When socket process is enabled, this could be called on background thread.
3856
3857 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)
3858 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)
;
3859
3860 if (mStopped) {
3861 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)
;
3862 return NS_OK;
3863 }
3864
3865 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"
, 3865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport"
") (" "OTA already called" ")"); do { *((volatile int*)__null
) = 3865; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3866
3867 AbortSession(aErrorCode);
3868 return NS_OK;
3869}
3870
3871// nsIRequestObserver (from nsIStreamListener)
3872
3873NS_IMETHODIMPnsresult
3874WebSocketChannel::OnStartRequest(nsIRequest* aRequest) {
3875 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)
3876 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)
;
3877 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"
, 3877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
3877; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3878 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"
, 3878); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mGotUpgradeOK"
") (" "OTA duplicated" ")"); do { *((volatile int*)__null) =
3878; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
3879
3880 if (mStopped) {
3881 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)
;
3882 AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED);
3883 return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED;
3884 }
3885
3886 nsresult rv;
3887 uint32_t status;
3888 char *val, *token;
3889
3890 rv = mHttpChannel->GetResponseStatus(&status);
3891 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3892 nsresult httpStatus;
3893 rv = NS_ERROR_WEBSOCKET_CONNECTION_REFUSED;
3894
3895 // If we failed to connect due to unsuccessful TLS handshake, we must
3896 // propagate a specific error to mozilla::dom::WebSocketImpl so it can set
3897 // status code to 1015. Otherwise return
3898 // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED.
3899 if (NS_SUCCEEDED(mHttpChannel->GetStatus(&httpStatus))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mHttpChannel->
GetStatus(&httpStatus))), 1)))
) {
3900 uint32_t errorClass;
3901 nsCOMPtr<nsINSSErrorsService> errSvc;
3902 errSvc = mozilla::components::NSSErrors::Service();
3903 // If GetErrorClass succeeds httpStatus is TLS related failure.
3904 if (errSvc &&
3905 NS_SUCCEEDED(errSvc->GetErrorClass(httpStatus, &errorClass))((bool)(__builtin_expect(!!(!NS_FAILED_impl(errSvc->GetErrorClass
(httpStatus, &errorClass))), 1)))
) {
3906 rv = NS_ERROR_NET_INADEQUATE_SECURITY;
3907 }
3908 }
3909
3910 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)
;
3911 AbortSession(rv);
3912 return rv;
3913 }
3914
3915 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)
;
3916 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
3917 do_QueryInterface(mHttpChannel);
3918 uint32_t versionMajor, versionMinor;
3919 rv = internalChannel->GetResponseVersion(&versionMajor, &versionMinor);
3920 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) ||
3921 !((versionMajor == 1 && versionMinor != 0) || versionMajor == 2) ||
3922 (versionMajor == 1 && status != 101) ||
3923 (versionMajor == 2 && status != 200)) {
3924 AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED);
3925 return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED;
3926 }
3927
3928 if (versionMajor == 1) {
3929 // These are only present on http/1.x websocket upgrades
3930 nsAutoCString respUpgrade;
3931 rv = mHttpChannel->GetResponseHeader("Upgrade"_ns, respUpgrade);
3932
3933 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3934 rv = NS_ERROR_ILLEGAL_VALUE;
3935 if (!respUpgrade.IsEmpty()) {
3936 val = respUpgrade.BeginWriting();
3937 while ((token = nsCRT::strtok(val, ", \t", &val))) {
3938 if (nsCRT::strcasecmp(token, "Websocket") == 0) {
3939 rv = NS_OK;
3940 break;
3941 }
3942 }
3943 }
3944 }
3945
3946 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3947 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)
3948 ("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)
3949 "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)
;
3950 AbortSession(NS_ERROR_ILLEGAL_VALUE);
3951 return rv;
3952 }
3953
3954 nsAutoCString respConnection;
3955 rv = mHttpChannel->GetResponseHeader("Connection"_ns, respConnection);
3956
3957 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3958 rv = NS_ERROR_ILLEGAL_VALUE;
3959 if (!respConnection.IsEmpty()) {
3960 val = respConnection.BeginWriting();
3961 while ((token = nsCRT::strtok(val, ", \t", &val))) {
3962 if (nsCRT::strcasecmp(token, "Upgrade") == 0) {
3963 rv = NS_OK;
3964 break;
3965 }
3966 }
3967 }
3968 }
3969
3970 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3971 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)
3972 ("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)
3973 "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)
;
3974 AbortSession(NS_ERROR_ILLEGAL_VALUE);
3975 return rv;
3976 }
3977
3978 nsAutoCString respAccept;
3979 rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Accept"_ns, respAccept);
3980
3981 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty() ||
3982 !respAccept.Equals(mHashedSecret)) {
3983 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)
3984 ("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)
3985 "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)
;
3986 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)
3987 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)
;
3988#ifdef FUZZING
3989 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty()) {
3990#endif
3991 AbortSession(NS_ERROR_ILLEGAL_VALUE);
3992 return NS_ERROR_ILLEGAL_VALUE;
3993#ifdef FUZZING
3994 }
3995#endif
3996 }
3997 }
3998
3999 // If we sent a sub protocol header, verify the response matches.
4000 // If response contains protocol that was not in request, fail.
4001 // If response contained no protocol header, set to "" so the protocol
4002 // attribute of the WebSocket JS object reflects that
4003 if (!mProtocol.IsEmpty()) {
4004 nsAutoCString respProtocol;
4005 rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Protocol"_ns,
4006 respProtocol);
4007 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4008 rv = NS_ERROR_ILLEGAL_VALUE;
4009 val = mProtocol.BeginWriting();
4010 while ((token = nsCRT::strtok(val, ", \t", &val))) {
4011 if (strcmp(token, respProtocol.get()) == 0) {
4012 rv = NS_OK;
4013 break;
4014 }
4015 }
4016
4017 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4018 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)
4019 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)
;
4020 mProtocol = respProtocol;
4021 } else {
4022 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)
4023 ("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)
4024 "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)
4025 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)
;
4026 mProtocol.Truncate();
4027 AbortSession(NS_ERROR_ILLEGAL_VALUE);
4028 return NS_ERROR_ILLEGAL_VALUE;
4029 }
4030 } else {
4031 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)
4032 ("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)
4033 "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)
4034 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)
;
4035 mProtocol.Truncate();
4036 }
4037 }
4038
4039 rv = HandleExtensions();
4040 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4041
4042 // Update mEffectiveURL for off main thread URI access.
4043 nsCOMPtr<nsIURI> uri = mURI ? mURI : mOriginalURI;
4044 nsAutoCString spec;
4045 rv = uri->GetSpec(spec);
4046 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"
, 4046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4046; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4047 CopyUTF8toUTF16(spec, mEffectiveURL);
4048
4049 mGotUpgradeOK = 1;
4050 if (mRecvdHttpUpgradeTransport) {
4051 // We're now done CONNECTING, which means we can now open another,
4052 // perhaps parallel, connection to the same host if one
4053 // is pending
4054 nsWSAdmissionManager::OnConnected(this);
4055
4056 return CallStartWebsocketData();
4057 }
4058
4059 return NS_OK;
4060}
4061
4062NS_IMETHODIMPnsresult
4063WebSocketChannel::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
4064 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)
4065 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)
;
4066 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"
, 4066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "not main thread" ")"); do { *((volatile int*)__null) =
4066; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4067
4068 // OnTransportAvailable won't be called if the request is stopped with
4069 // an error. Abort the session now instead of waiting for timeout.
4070 if (NS_FAILED(aStatusCode)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatusCode)), 0))
)
&& !mRecvdHttpUpgradeTransport) {
4071 AbortSession(aStatusCode);
4072 }
4073
4074 ReportConnectionTelemetry(aStatusCode);
4075
4076 // This is the end of the HTTP upgrade transaction, the
4077 // upgraded streams live on
4078
4079 mChannel = nullptr;
4080 mHttpChannel = nullptr;
4081 mLoadGroup = nullptr;
4082 mCallbacks = nullptr;
4083
4084 return NS_OK;
4085}
4086
4087// nsIInputStreamCallback
4088
4089NS_IMETHODIMPnsresult
4090WebSocketChannel::OnInputStreamReady(nsIAsyncInputStream* aStream) {
4091 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)
;
4092 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"
, 4092); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 4092; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4093
4094 if (!mSocketIn) { // did we we clean up the socket after scheduling
4095 // InputReady?
4096 return NS_OK;
4097 }
4098
4099 // this is after the http upgrade - so we are speaking websockets
4100 char buffer[2048];
4101 uint32_t count;
4102 nsresult rv;
4103
4104 do {
4105 rv = mSocketIn->Read((char*)buffer, sizeof(buffer), &count);
4106 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)
4107 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)
;
4108
4109 if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
4110 mSocketIn->AsyncWait(this, 0, 0, mIOThread);
4111 return NS_OK;
4112 }
4113
4114 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4115 AbortSession(rv);
4116 return rv;
4117 }
4118
4119 if (count == 0) {
4120 AbortSession(NS_BASE_STREAM_CLOSED);
4121 return NS_OK;
4122 }
4123
4124 if (mStopped) {
4125 continue;
4126 }
4127
4128 rv = ProcessInput((uint8_t*)buffer, count);
4129 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4130 AbortSession(rv);
4131 return rv;
4132 }
4133 } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mSocketIn);
4134
4135 return NS_OK;
4136}
4137
4138// nsIOutputStreamCallback
4139
4140NS_IMETHODIMPnsresult
4141WebSocketChannel::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
4142 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)
;
4143 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"
, 4143); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 4143; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4144 nsresult rv;
4145
4146 if (!mCurrentOut) PrimeNewOutgoingMessage();
4147
4148 while (mCurrentOut && mSocketOut) {
4149 const char* sndBuf;
4150 uint32_t toSend;
4151 uint32_t amtSent;
4152
4153 if (mHdrOut) {
4154 sndBuf = (const char*)mHdrOut;
4155 toSend = mHdrOutToSend;
4156 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)
4157 ("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)
4158 "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)
4159 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)
;
4160 } else {
4161 sndBuf = (char*)mCurrentOut->BeginReading() + mCurrentOutSent;
4162 toSend = mCurrentOut->Length() - mCurrentOutSent;
4163 if (toSend > 0) {
4164 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)
4165 ("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)
4166 "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)
4167 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)
;
4168 }
4169 }
4170
4171 if (toSend == 0) {
4172 amtSent = 0;
4173 } else {
4174 rv = mSocketOut->Write(sndBuf, toSend, &amtSent);
4175 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)
4176 "\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)
4177 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)
;
4178
4179 if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
4180 mSocketOut->AsyncWait(this, 0, 0, mIOThread);
4181 return NS_OK;
4182 }
4183
4184 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4185 AbortSession(rv);
4186 return NS_OK;
4187 }
4188 }
4189
4190 if (mHdrOut) {
4191 if (amtSent == toSend) {
4192 mHdrOut = nullptr;
4193 mHdrOutToSend = 0;
4194 } else {
4195 mHdrOut += amtSent;
4196 mHdrOutToSend -= amtSent;
4197 mSocketOut->AsyncWait(this, 0, 0, mIOThread);
4198 }
4199 } else {
4200 if (amtSent == toSend) {
4201 if (!mStopped) {
4202 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
4203 target->Dispatch(
4204 new CallAcknowledge(this, mCurrentOut->OrigLength()),
4205 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
4206 } else {
4207 return NS_ERROR_UNEXPECTED;
4208 }
4209 }
4210 DeleteCurrentOutGoingMessage();
4211 PrimeNewOutgoingMessage();
4212 } else {
4213 mCurrentOutSent += amtSent;
4214 mSocketOut->AsyncWait(this, 0, 0, mIOThread);
4215 }
4216 }
4217 }
4218
4219 if (mReleaseOnTransmit) ReleaseSession();
4220 return NS_OK;
4221}
4222
4223// nsIStreamListener
4224
4225NS_IMETHODIMPnsresult
4226WebSocketChannel::OnDataAvailable(nsIRequest* aRequest,
4227 nsIInputStream* aInputStream,
4228 uint64_t aOffset, uint32_t aCount) {
4229 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)
4230 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)
;
4231
4232 // This is the HTTP OnDataAvailable Method, which means this is http data in
4233 // response to the upgrade request and there should be no http response body
4234 // if the upgrade succeeded. This generally should be caught by a non 101
4235 // response code in OnStartRequest().. so we can ignore the data here
4236
4237 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)
4238 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)
;
4239
4240 return NS_OK;
4241}
4242
4243void WebSocketChannel::DoEnqueueOutgoingMessage() {
4244 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)
;
4245 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"
, 4245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()"
") (" "not on right thread" ")"); do { *((volatile int*)__null
) = 4245; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4246
4247 if (!mCurrentOut) {
4248 PrimeNewOutgoingMessage();
4249 }
4250
4251 while (mCurrentOut && mConnection) {
4252 nsresult rv = NS_OK;
4253 if (mCurrentOut->Length() - mCurrentOutSent == 0) {
4254 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)
4255 ("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)
4256 "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)
4257 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)
;
4258 rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, nullptr, 0);
4259 } else {
4260 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)
4261 ("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)
4262 "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)
4263 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)
;
4264 rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend,
4265 (uint8_t*)mCurrentOut->BeginReading(),
4266 mCurrentOut->Length());
4267 }
4268
4269 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)
4270 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)
;
4271 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4272 AbortSession(rv);
4273 return;
4274 }
4275
4276 if (!mStopped) {
4277 // TODO: Currently, we assume that data is completely written to the
4278 // socket after sending it to socket process, but it's not true. The data
4279 // could be queued in socket process and waiting for the socket to be able
4280 // to write. We should implement flow control for this in bug 1726552.
4281 if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) {
4282 target->Dispatch(new CallAcknowledge(this, mCurrentOut->OrigLength()),
4283 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
4284 } else {
4285 AbortSession(NS_ERROR_UNEXPECTED);
4286 return;
4287 }
4288 }
4289 DeleteCurrentOutGoingMessage();
4290 PrimeNewOutgoingMessage();
4291 }
4292
4293 if (mReleaseOnTransmit) {
4294 ReleaseSession();
4295 }
4296}
4297
4298void WebSocketChannel::OnError(nsresult aStatus) { AbortSession(aStatus); }
4299
4300void WebSocketChannel::OnTCPClosed() { mTCPClosed = true; }
4301
4302nsresult WebSocketChannel::OnDataReceived(uint8_t* aData, uint32_t aCount) {
4303 return ProcessInput(aData, aCount);
4304}
4305
4306} // namespace mozilla::net
4307
4308#undef CLOSE_GOING_AWAY