File: | var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp |
Warning: | line 2676, column 3 Value stored to 'rv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | /* vim: set sw=2 ts=8 et tw=80 : */ |
3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | |
7 | #include <algorithm> |
8 | |
9 | #include "WebSocketChannel.h" |
10 | |
11 | #include "WebSocketConnectionBase.h" |
12 | #include "WebSocketFrame.h" |
13 | #include "WebSocketLog.h" |
14 | #include "mozilla/Atomics.h" |
15 | #include "mozilla/Attributes.h" |
16 | #include "mozilla/Base64.h" |
17 | #include "mozilla/Components.h" |
18 | #include "mozilla/EndianUtils.h" |
19 | #include "mozilla/MathAlgorithms.h" |
20 | #include "mozilla/ScopeExit.h" |
21 | #include "mozilla/StaticMutex.h" |
22 | #include "mozilla/StaticPrefs_privacy.h" |
23 | #include "mozilla/Telemetry.h" |
24 | #include "mozilla/TimeStamp.h" |
25 | #include "mozilla/Utf8.h" |
26 | #include "mozilla/net/WebSocketEventService.h" |
27 | #include "nsCRT.h" |
28 | #include "nsCharSeparatedTokenizer.h" |
29 | #include "nsComponentManagerUtils.h" |
30 | #include "nsError.h" |
31 | #include "nsIAsyncVerifyRedirectCallback.h" |
32 | #include "nsICancelable.h" |
33 | #include "nsIChannel.h" |
34 | #include "nsIClassOfService.h" |
35 | #include "nsICryptoHash.h" |
36 | #include "nsIDNSRecord.h" |
37 | #include "nsIDNSService.h" |
38 | #include "nsIDashboardEventNotifier.h" |
39 | #include "nsIEventTarget.h" |
40 | #include "nsIHttpChannel.h" |
41 | #include "nsIIOService.h" |
42 | #include "nsINSSErrorsService.h" |
43 | #include "nsINetworkLinkService.h" |
44 | #include "nsINode.h" |
45 | #include "nsIObserverService.h" |
46 | #include "nsIPrefBranch.h" |
47 | #include "nsIProtocolHandler.h" |
48 | #include "nsIProtocolProxyService.h" |
49 | #include "nsIProxiedChannel.h" |
50 | #include "nsIProxyInfo.h" |
51 | #include "nsIRandomGenerator.h" |
52 | #include "nsIRunnable.h" |
53 | #include "nsISocketTransport.h" |
54 | #include "nsITLSSocketControl.h" |
55 | #include "nsITransportProvider.h" |
56 | #include "nsITransportSecurityInfo.h" |
57 | #include "nsIURI.h" |
58 | #include "nsIURIMutator.h" |
59 | #include "nsNetCID.h" |
60 | #include "nsNetUtil.h" |
61 | #include "nsProxyRelease.h" |
62 | #include "nsServiceManagerUtils.h" |
63 | #include "nsSocketTransportService2.h" |
64 | #include "nsStringStream.h" |
65 | #include "nsThreadUtils.h" |
66 | #include "plbase64.h" |
67 | #include "prmem.h" |
68 | #include "prnetdb.h" |
69 | #include "zlib.h" |
70 | |
71 | // rather than slurp up all of nsIWebSocket.idl, which lives outside necko, just |
72 | // dupe one constant we need from it |
73 | #define CLOSE_GOING_AWAY 1001 |
74 | |
75 | using namespace mozilla; |
76 | using namespace mozilla::net; |
77 | |
78 | namespace mozilla::net { |
79 | |
80 | NS_IMPL_ISUPPORTS(WebSocketChannel, nsIWebSocketChannel, nsIHttpUpgradeListener,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 85 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast <void*>(this), aIID, aInstancePtr, table); return rv; } |
81 | nsIRequestObserver, nsIStreamListener, nsIProtocolHandler,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 85 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast <void*>(this), aIID, aInstancePtr, table); return rv; } |
82 | nsIInputStreamCallback, nsIOutputStreamCallback,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 85 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast <void*>(this), aIID, aInstancePtr, table); return rv; } |
83 | nsITimerCallback, nsIDNSListener, nsIProtocolProxyCallback,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 85 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast <void*>(this), aIID, aInstancePtr, table); return rv; } |
84 | nsIInterfaceRequestor, nsIChannelEventSink,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 85 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast <void*>(this), aIID, aInstancePtr, table); return rv; } |
85 | nsIThreadRetargetableRequest, nsIObserver, nsINamed)MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 85 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 85; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 85); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast <void*>(this), aIID, aInstancePtr, table); return rv; } |
86 | |
87 | // We implement RFC 6455, which uses Sec-WebSocket-Version: 13 on the wire. |
88 | #define SEC_WEBSOCKET_VERSION"13" "13" |
89 | |
90 | /* |
91 | * About SSL unsigned certificates |
92 | * |
93 | * wss will not work to a host using an unsigned certificate unless there |
94 | * is already an exception (i.e. it cannot popup a dialog asking for |
95 | * a security exception). This is similar to how an inlined img will |
96 | * fail without a dialog if fails for the same reason. This should not |
97 | * be a problem in practice as it is expected the websocket javascript |
98 | * is served from the same host as the websocket server (or of course, |
99 | * a valid cert could just be provided). |
100 | * |
101 | */ |
102 | |
103 | // some helper classes |
104 | |
105 | //----------------------------------------------------------------------------- |
106 | // FailDelayManager |
107 | // |
108 | // Stores entries (searchable by {host, port}) of connections that have recently |
109 | // failed, so we can do delay of reconnects per RFC 6455 Section 7.2.3 |
110 | //----------------------------------------------------------------------------- |
111 | |
112 | // Initial reconnect delay is randomly chosen between 200-400 ms. |
113 | // This is a gentler backoff than the 0-5 seconds the spec offhandedly suggests. |
114 | const uint32_t kWSReconnectInitialBaseDelay = 200; |
115 | const uint32_t kWSReconnectInitialRandomDelay = 200; |
116 | |
117 | // Base lifetime (in ms) of a FailDelay: kept longer if more failures occur |
118 | const uint32_t kWSReconnectBaseLifeTime = 60 * 1000; |
119 | // Maximum reconnect delay (in ms) |
120 | const uint32_t kWSReconnectMaxDelay = 60 * 1000; |
121 | |
122 | // hold record of failed connections, and calculates needed delay for reconnects |
123 | // to same host/path/port. |
124 | class FailDelay { |
125 | public: |
126 | FailDelay(nsCString address, nsCString path, int32_t port) |
127 | : mAddress(std::move(address)), mPath(std::move(path)), mPort(port) { |
128 | mLastFailure = TimeStamp::Now(); |
129 | mNextDelay = kWSReconnectInitialBaseDelay + |
130 | (rand() % kWSReconnectInitialRandomDelay); |
131 | } |
132 | |
133 | // Called to update settings when connection fails again. |
134 | void FailedAgain() { |
135 | mLastFailure = TimeStamp::Now(); |
136 | // We use a truncated exponential backoff as suggested by RFC 6455, |
137 | // but multiply by 1.5 instead of 2 to be more gradual. |
138 | mNextDelay = static_cast<uint32_t>( |
139 | std::min<double>(kWSReconnectMaxDelay, mNextDelay * 1.5)); |
140 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
141 | ("WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
142 | "to "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
143 | "%" PRIu32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
144 | mAddress.get(), mPath.get(), mPort, mNextDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0); |
145 | } |
146 | |
147 | // returns 0 if there is no need to delay (i.e. delay interval is over) |
148 | uint32_t RemainingDelay(TimeStamp rightNow) { |
149 | TimeDuration dur = rightNow - mLastFailure; |
150 | uint32_t sinceFail = (uint32_t)dur.ToMilliseconds(); |
151 | if (sinceFail > mNextDelay) return 0; |
152 | |
153 | return mNextDelay - sinceFail; |
154 | } |
155 | |
156 | bool IsExpired(TimeStamp rightNow) { |
157 | return (mLastFailure + TimeDuration::FromMilliseconds( |
158 | kWSReconnectBaseLifeTime + mNextDelay)) <= |
159 | rightNow; |
160 | } |
161 | |
162 | nsCString mAddress; // IP address (or hostname if using proxy) |
163 | nsCString mPath; |
164 | int32_t mPort; |
165 | |
166 | private: |
167 | TimeStamp mLastFailure; // Time of last failed attempt |
168 | // mLastFailure + mNextDelay is the soonest we'll allow a reconnect |
169 | uint32_t mNextDelay; // milliseconds |
170 | }; |
171 | |
172 | class FailDelayManager { |
173 | public: |
174 | FailDelayManager() { |
175 | MOZ_COUNT_CTOR(FailDelayManager)do { static_assert(std::is_class_v<FailDelayManager>, "Token '" "FailDelayManager" "' is not a class type."); static_assert( !std::is_base_of<nsISupports, FailDelayManager>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR" );; NS_LogCtor((void*)this, "FailDelayManager", sizeof(*this) ); } while (0); |
176 | |
177 | mDelaysDisabled = false; |
178 | |
179 | nsCOMPtr<nsIPrefBranch> prefService; |
180 | prefService = mozilla::components::Preferences::Service(); |
181 | if (!prefService) { |
182 | return; |
183 | } |
184 | bool boolpref = true; |
185 | nsresult rv; |
186 | rv = prefService->GetBoolPref("network.websocket.delay-failed-reconnects", |
187 | &boolpref); |
188 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !boolpref) { |
189 | mDelaysDisabled = true; |
190 | } |
191 | } |
192 | |
193 | ~FailDelayManager() { MOZ_COUNT_DTOR(FailDelayManager)do { static_assert(std::is_class_v<FailDelayManager>, "Token '" "FailDelayManager" "' is not a class type."); static_assert( !std::is_base_of<nsISupports, FailDelayManager>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR" );; NS_LogDtor((void*)this, "FailDelayManager", sizeof(*this) ); } while (0); } |
194 | |
195 | void Add(nsCString& address, nsCString& path, int32_t port) { |
196 | if (mDelaysDisabled) return; |
197 | |
198 | UniquePtr<FailDelay> record(new FailDelay(address, path, port)); |
199 | mEntries.AppendElement(std::move(record)); |
200 | } |
201 | |
202 | // Element returned may not be valid after next main thread event: don't keep |
203 | // pointer to it around |
204 | FailDelay* Lookup(nsCString& address, nsCString& path, int32_t port, |
205 | uint32_t* outIndex = nullptr) { |
206 | if (mDelaysDisabled) return nullptr; |
207 | |
208 | FailDelay* result = nullptr; |
209 | TimeStamp rightNow = TimeStamp::Now(); |
210 | |
211 | // We also remove expired entries during search: iterate from end to make |
212 | // indexing simpler |
213 | for (int32_t i = mEntries.Length() - 1; i >= 0; --i) { |
214 | FailDelay* fail = mEntries[i].get(); |
215 | if (fail->mAddress.Equals(address) && fail->mPath.Equals(path) && |
216 | fail->mPort == port) { |
217 | if (outIndex) *outIndex = i; |
218 | result = fail; |
219 | // break here: removing more entries would mess up *outIndex. |
220 | // Any remaining expired entries will be deleted next time Lookup |
221 | // finds nothing, which is the most common case anyway. |
222 | break; |
223 | } |
224 | if (fail->IsExpired(rightNow)) { |
225 | mEntries.RemoveElementAt(i); |
226 | } |
227 | } |
228 | return result; |
229 | } |
230 | |
231 | // returns true if channel connects immediately, or false if it's delayed |
232 | void DelayOrBegin(WebSocketChannel* ws) { |
233 | if (!mDelaysDisabled) { |
234 | uint32_t failIndex = 0; |
235 | FailDelay* fail = Lookup(ws->mAddress, ws->mPath, ws->mPort, &failIndex); |
236 | |
237 | if (fail) { |
238 | TimeStamp rightNow = TimeStamp::Now(); |
239 | |
240 | uint32_t remainingDelay = fail->RemainingDelay(rightNow); |
241 | if (remainingDelay) { |
242 | // reconnecting within delay interval: delay by remaining time |
243 | nsresult rv; |
244 | MutexAutoLock lock(ws->mMutex); |
245 | rv = NS_NewTimerWithCallback(getter_AddRefs(ws->mReconnectDelayTimer), |
246 | ws, remainingDelay, |
247 | nsITimer::TYPE_ONE_SHOT); |
248 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
249 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0) |
250 | ("WebSocket: delaying websocket [this=%p] by %lu ms, changing"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0) |
251 | " state to CONNECTING_DELAYED",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0) |
252 | ws, (unsigned long)remainingDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0); |
253 | ws->mConnecting = CONNECTING_DELAYED; |
254 | return; |
255 | } |
256 | // if timer fails (which is very unlikely), drop down to BeginOpen |
257 | // call |
258 | } else if (fail->IsExpired(rightNow)) { |
259 | mEntries.RemoveElementAt(failIndex); |
260 | } |
261 | } |
262 | } |
263 | |
264 | // Delays disabled, or no previous failure, or we're reconnecting after |
265 | // scheduled delay interval has passed: connect. |
266 | ws->BeginOpen(true); |
267 | } |
268 | |
269 | // Remove() also deletes all expired entries as it iterates: better for |
270 | // battery life than using a periodic timer. |
271 | void Remove(nsCString& address, nsCString& path, int32_t port) { |
272 | TimeStamp rightNow = TimeStamp::Now(); |
273 | |
274 | // iterate from end, to make deletion indexing easier |
275 | for (int32_t i = mEntries.Length() - 1; i >= 0; --i) { |
276 | FailDelay* entry = mEntries[i].get(); |
277 | if ((entry->mAddress.Equals(address) && entry->mPath.Equals(path) && |
278 | entry->mPort == port) || |
279 | entry->IsExpired(rightNow)) { |
280 | mEntries.RemoveElementAt(i); |
281 | } |
282 | } |
283 | } |
284 | |
285 | private: |
286 | nsTArray<UniquePtr<FailDelay>> mEntries; |
287 | bool mDelaysDisabled; |
288 | }; |
289 | |
290 | //----------------------------------------------------------------------------- |
291 | // nsWSAdmissionManager |
292 | // |
293 | // 1) Ensures that only one websocket at a time is CONNECTING to a given IP |
294 | // address (or hostname, if using proxy), per RFC 6455 Section 4.1. |
295 | // 2) Delays reconnects to IP/host after connection failure, per Section 7.2.3 |
296 | //----------------------------------------------------------------------------- |
297 | |
298 | class nsWSAdmissionManager { |
299 | public: |
300 | static void Init() { |
301 | StaticMutexAutoLock lock(sLock); |
302 | if (!sManager) { |
303 | sManager = new nsWSAdmissionManager(); |
304 | } |
305 | } |
306 | |
307 | static void Shutdown() { |
308 | StaticMutexAutoLock lock(sLock); |
309 | delete sManager; |
310 | sManager = nullptr; |
311 | } |
312 | |
313 | // Determine if we will open connection immediately (returns true), or |
314 | // delay/queue the connection (returns false) |
315 | static void ConditionallyConnect(WebSocketChannel* ws) { |
316 | LOG(("Websocket: ConditionallyConnect: [this=%p]", ws))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: ConditionallyConnect: [this=%p]" , ws); } } while (0); |
317 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 317; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
318 | MOZ_ASSERT(ws->mConnecting == NOT_CONNECTING, "opening state")do { static_assert( mozilla::detail::AssertionConditionType< decltype(ws->mConnecting == NOT_CONNECTING)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ws->mConnecting == NOT_CONNECTING ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "ws->mConnecting == NOT_CONNECTING" " (" "opening state" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ws->mConnecting == NOT_CONNECTING" ") (" "opening state" ")"); do { *((volatile int*)__null) = 318 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
319 | |
320 | StaticMutexAutoLock lock(sLock); |
321 | if (!sManager) { |
322 | return; |
323 | } |
324 | |
325 | // If there is already another WS channel connecting to this IP address, |
326 | // defer BeginOpen and mark as waiting in queue. |
327 | bool hostFound = (sManager->IndexOf(ws->mAddress, ws->mOriginSuffix) >= 0); |
328 | |
329 | uint32_t failIndex = 0; |
330 | FailDelay* fail = sManager->mFailures.Lookup(ws->mAddress, ws->mPath, |
331 | ws->mPort, &failIndex); |
332 | bool existingFail = fail != nullptr; |
333 | |
334 | // Always add ourselves to queue, even if we'll connect immediately |
335 | UniquePtr<nsOpenConn> newdata( |
336 | new nsOpenConn(ws->mAddress, ws->mOriginSuffix, existingFail, ws)); |
337 | |
338 | // If a connection has not previously failed then prioritize it over |
339 | // connections that have |
340 | if (existingFail) { |
341 | sManager->mQueue.AppendElement(std::move(newdata)); |
342 | } else { |
343 | uint32_t insertionIndex = sManager->IndexOfFirstFailure(); |
344 | MOZ_ASSERT(insertionIndex <= sManager->mQueue.Length(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(insertionIndex <= sManager->mQueue.Length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(insertionIndex <= sManager->mQueue.Length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("insertionIndex <= sManager->mQueue.Length()" " (" "Insertion index outside bounds" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()" ") (" "Insertion index outside bounds" ")"); do { *((volatile int*)__null) = 345; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
345 | "Insertion index outside bounds")do { static_assert( mozilla::detail::AssertionConditionType< decltype(insertionIndex <= sManager->mQueue.Length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(insertionIndex <= sManager->mQueue.Length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("insertionIndex <= sManager->mQueue.Length()" " (" "Insertion index outside bounds" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()" ") (" "Insertion index outside bounds" ")"); do { *((volatile int*)__null) = 345; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
346 | sManager->mQueue.InsertElementAt(insertionIndex, std::move(newdata)); |
347 | } |
348 | |
349 | if (hostFound) { |
350 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to " "CONNECTING_QUEUED"); } } while (0) |
351 | ("Websocket: some other channel is connecting, changing state to "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to " "CONNECTING_QUEUED"); } } while (0) |
352 | "CONNECTING_QUEUED"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to " "CONNECTING_QUEUED"); } } while (0); |
353 | ws->mConnecting = CONNECTING_QUEUED; |
354 | } else { |
355 | sManager->mFailures.DelayOrBegin(ws); |
356 | } |
357 | } |
358 | |
359 | static void OnConnected(WebSocketChannel* aChannel) { |
360 | LOG(("Websocket: OnConnected: [this=%p]", aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnConnected: [this=%p]" , aChannel); } } while (0); |
361 | |
362 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 362; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
363 | MOZ_ASSERT(aChannel->mConnecting == CONNECTING_IN_PROGRESS,do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChannel->mConnecting == CONNECTING_IN_PROGRESS)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aChannel->mConnecting == CONNECTING_IN_PROGRESS)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChannel->mConnecting == CONNECTING_IN_PROGRESS" " (" "Channel completed connect, but not connecting?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS" ") (" "Channel completed connect, but not connecting?" ")"); do { *((volatile int*)__null) = 364; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false) |
364 | "Channel completed connect, but not connecting?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChannel->mConnecting == CONNECTING_IN_PROGRESS)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aChannel->mConnecting == CONNECTING_IN_PROGRESS)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChannel->mConnecting == CONNECTING_IN_PROGRESS" " (" "Channel completed connect, but not connecting?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS" ") (" "Channel completed connect, but not connecting?" ")"); do { *((volatile int*)__null) = 364; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false); |
365 | |
366 | StaticMutexAutoLock lock(sLock); |
367 | if (!sManager) { |
368 | return; |
369 | } |
370 | |
371 | LOG(("Websocket: changing state to NOT_CONNECTING"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to NOT_CONNECTING" ); } } while (0); |
372 | aChannel->mConnecting = NOT_CONNECTING; |
373 | |
374 | // Remove from queue |
375 | sManager->RemoveFromQueue(aChannel); |
376 | |
377 | // Connection succeeded, so stop keeping track of any previous failures |
378 | sManager->mFailures.Remove(aChannel->mAddress, aChannel->mPath, |
379 | aChannel->mPort); |
380 | |
381 | // Check for queued connections to same host. |
382 | // Note: still need to check for failures, since next websocket with same |
383 | // host may have different port |
384 | sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix); |
385 | } |
386 | |
387 | // Called every time a websocket channel ends its session (including going |
388 | // away w/o ever successfully creating a connection) |
389 | static void OnStopSession(WebSocketChannel* aChannel, nsresult aReason) { |
390 | LOG(("Websocket: OnStopSession: [this=%p, reason=0x%08" PRIx32 "]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnStopSession: [this=%p, reason=0x%08" "x" "]", aChannel, static_cast<uint32_t>(aReason)); } } while (0) |
391 | aChannel, static_cast<uint32_t>(aReason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnStopSession: [this=%p, reason=0x%08" "x" "]", aChannel, static_cast<uint32_t>(aReason)); } } while (0); |
392 | |
393 | StaticMutexAutoLock lock(sLock); |
394 | if (!sManager) { |
395 | return; |
396 | } |
397 | |
398 | if (NS_FAILED(aReason)((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0)))) { |
399 | // Have we seen this failure before? |
400 | FailDelay* knownFailure = sManager->mFailures.Lookup( |
401 | aChannel->mAddress, aChannel->mPath, aChannel->mPort); |
402 | if (knownFailure) { |
403 | if (aReason == NS_ERROR_NOT_CONNECTED) { |
404 | // Don't count close() before connection as a network error |
405 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
406 | ("Websocket close() before connection to %s, %s, %d completed"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
407 | " [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
408 | aChannel->mAddress.get(), aChannel->mPath.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
409 | (int)aChannel->mPort, aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0); |
410 | } else { |
411 | // repeated failure to connect: increase delay for next connection |
412 | knownFailure->FailedAgain(); |
413 | } |
414 | } else { |
415 | // new connection failure: record it. |
416 | LOG(("WebSocket: connection to %s, %s, %d failed: [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]" , aChannel->mAddress.get(), aChannel->mPath.get(), (int )aChannel->mPort, aChannel); } } while (0) |
417 | aChannel->mAddress.get(), aChannel->mPath.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]" , aChannel->mAddress.get(), aChannel->mPath.get(), (int )aChannel->mPort, aChannel); } } while (0) |
418 | (int)aChannel->mPort, aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]" , aChannel->mAddress.get(), aChannel->mPath.get(), (int )aChannel->mPort, aChannel); } } while (0); |
419 | sManager->mFailures.Add(aChannel->mAddress, aChannel->mPath, |
420 | aChannel->mPort); |
421 | } |
422 | } |
423 | |
424 | if (NS_IsMainThread()) { |
425 | ContinueOnStopSession(aChannel, aReason); |
426 | } else { |
427 | NS_DispatchToMainThread(NS_NewRunnableFunction( |
428 | "nsWSAdmissionManager::ContinueOnStopSession", |
429 | [channel = RefPtr{aChannel}, reason = aReason]() { |
430 | StaticMutexAutoLock lock(sLock); |
431 | if (!sManager) { |
432 | return; |
433 | } |
434 | |
435 | nsWSAdmissionManager::ContinueOnStopSession(channel, reason); |
436 | })); |
437 | } |
438 | } |
439 | |
440 | static void ContinueOnStopSession(WebSocketChannel* aChannel, |
441 | nsresult aReason) { |
442 | sLock.AssertCurrentThreadOwns(); |
443 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 443; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
444 | |
445 | if (!aChannel->mConnecting) { |
446 | return; |
447 | } |
448 | |
449 | // Only way a connecting channel may get here w/o failing is if it |
450 | // was closed with GOING_AWAY (1001) because of navigation, tab |
451 | // close, etc. |
452 | #ifdef DEBUG1 |
453 | { |
454 | MutexAutoLock lock(aChannel->mMutex); |
455 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" " (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" ") (" "websocket closed while connecting w/o failing?" ")"); do { *((volatile int*)__null) = 457; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false) |
456 | NS_FAILED(aReason) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY,do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" " (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" ") (" "websocket closed while connecting w/o failing?" ")"); do { *((volatile int*)__null) = 457; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false) |
457 | "websocket closed while connecting w/o failing?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" " (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" ") (" "websocket closed while connecting w/o failing?" ")"); do { *((volatile int*)__null) = 457; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false); |
458 | } |
459 | #endif |
460 | Unused << aReason; |
461 | |
462 | sManager->RemoveFromQueue(aChannel); |
463 | |
464 | bool wasNotQueued = (aChannel->mConnecting != CONNECTING_QUEUED); |
465 | LOG(("Websocket: changing state to NOT_CONNECTING"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to NOT_CONNECTING" ); } } while (0); |
466 | aChannel->mConnecting = NOT_CONNECTING; |
467 | if (wasNotQueued) { |
468 | sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix); |
469 | } |
470 | } |
471 | |
472 | static void IncrementSessionCount() { |
473 | StaticMutexAutoLock lock(sLock); |
474 | if (!sManager) { |
475 | return; |
476 | } |
477 | sManager->mSessionCount++; |
478 | } |
479 | |
480 | static void DecrementSessionCount() { |
481 | StaticMutexAutoLock lock(sLock); |
482 | if (!sManager) { |
483 | return; |
484 | } |
485 | sManager->mSessionCount--; |
486 | } |
487 | |
488 | static void GetSessionCount(int32_t& aSessionCount) { |
489 | StaticMutexAutoLock lock(sLock); |
490 | if (!sManager) { |
491 | return; |
492 | } |
493 | aSessionCount = sManager->mSessionCount; |
494 | } |
495 | |
496 | private: |
497 | nsWSAdmissionManager() : mSessionCount(0) { |
498 | MOZ_COUNT_CTOR(nsWSAdmissionManager)do { static_assert(std::is_class_v<nsWSAdmissionManager> , "Token '" "nsWSAdmissionManager" "' is not a class type."); static_assert(!std::is_base_of<nsISupports, nsWSAdmissionManager >::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsWSAdmissionManager" , sizeof(*this)); } while (0); |
499 | } |
500 | |
501 | ~nsWSAdmissionManager() { MOZ_COUNT_DTOR(nsWSAdmissionManager)do { static_assert(std::is_class_v<nsWSAdmissionManager> , "Token '" "nsWSAdmissionManager" "' is not a class type."); static_assert(!std::is_base_of<nsISupports, nsWSAdmissionManager >::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsWSAdmissionManager" , sizeof(*this)); } while (0); } |
502 | |
503 | class nsOpenConn { |
504 | public: |
505 | nsOpenConn(nsCString& addr, nsCString& originSuffix, bool failed, |
506 | WebSocketChannel* channel) |
507 | : mAddress(addr), |
508 | mOriginSuffix(originSuffix), |
509 | mFailed(failed), |
510 | mChannel(channel) { |
511 | MOZ_COUNT_CTOR(nsOpenConn)do { static_assert(std::is_class_v<nsOpenConn>, "Token '" "nsOpenConn" "' is not a class type."); static_assert(!std:: is_base_of<nsISupports, nsOpenConn>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsOpenConn", sizeof (*this)); } while (0); |
512 | } |
513 | MOZ_COUNTED_DTOR(nsOpenConn)~nsOpenConn() { do { static_assert(std::is_class_v<nsOpenConn >, "Token '" "nsOpenConn" "' is not a class type."); static_assert (!std::is_base_of<nsISupports, nsOpenConn>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsOpenConn", sizeof (*this)); } while (0); } |
514 | |
515 | nsCString mAddress; |
516 | nsCString mOriginSuffix; |
517 | bool mFailed = false; |
518 | RefPtr<WebSocketChannel> mChannel; |
519 | }; |
520 | |
521 | void ConnectNext(nsCString& hostName, nsCString& originSuffix) { |
522 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 522; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
523 | |
524 | int32_t index = IndexOf(hostName, originSuffix); |
525 | if (index >= 0) { |
526 | WebSocketChannel* chan = mQueue[index]->mChannel; |
527 | |
528 | MOZ_ASSERT(chan->mConnecting == CONNECTING_QUEUED,do { static_assert( mozilla::detail::AssertionConditionType< decltype(chan->mConnecting == CONNECTING_QUEUED)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(chan->mConnecting == CONNECTING_QUEUED))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("chan->mConnecting == CONNECTING_QUEUED" " (" "transaction not queued but in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED" ") (" "transaction not queued but in queue" ")"); do { *((volatile int*)__null) = 529; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
529 | "transaction not queued but in queue")do { static_assert( mozilla::detail::AssertionConditionType< decltype(chan->mConnecting == CONNECTING_QUEUED)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(chan->mConnecting == CONNECTING_QUEUED))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("chan->mConnecting == CONNECTING_QUEUED" " (" "transaction not queued but in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 529); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED" ") (" "transaction not queued but in queue" ")"); do { *((volatile int*)__null) = 529; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
530 | LOG(("WebSocket: ConnectNext: found channel [this=%p] in queue", chan))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: ConnectNext: found channel [this=%p] in queue" , chan); } } while (0); |
531 | |
532 | mFailures.DelayOrBegin(chan); |
533 | } |
534 | } |
535 | |
536 | void RemoveFromQueue(WebSocketChannel* aChannel) { |
537 | LOG(("Websocket: RemoveFromQueue: [this=%p]", aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: RemoveFromQueue: [this=%p]" , aChannel); } } while (0); |
538 | int32_t index = IndexOf(aChannel); |
539 | MOZ_ASSERT(index >= 0, "connection to remove not in queue")do { static_assert( mozilla::detail::AssertionConditionType< decltype(index >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(index >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("index >= 0" " (" "connection to remove not in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index >= 0" ") (" "connection to remove not in queue" ")"); do { *((volatile int*)__null) = 539; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
540 | if (index >= 0) { |
541 | mQueue.RemoveElementAt(index); |
542 | } |
543 | } |
544 | |
545 | int32_t IndexOf(nsCString& aAddress, nsCString& aOriginSuffix) { |
546 | for (uint32_t i = 0; i < mQueue.Length(); i++) { |
547 | bool isPartitioned = StaticPrefs::privacy_partition_network_state() || |
548 | StaticPrefs::privacy_firstparty_isolate(); |
549 | if (aAddress == (mQueue[i])->mAddress && |
550 | (!isPartitioned || aOriginSuffix == (mQueue[i])->mOriginSuffix)) { |
551 | return i; |
552 | } |
553 | } |
554 | return -1; |
555 | } |
556 | |
557 | int32_t IndexOf(WebSocketChannel* aChannel) { |
558 | for (uint32_t i = 0; i < mQueue.Length(); i++) { |
559 | if (aChannel == (mQueue[i])->mChannel) return i; |
560 | } |
561 | return -1; |
562 | } |
563 | |
564 | // Returns the index of the first entry that failed, or else the last entry if |
565 | // none found |
566 | uint32_t IndexOfFirstFailure() { |
567 | for (uint32_t i = 0; i < mQueue.Length(); i++) { |
568 | if (mQueue[i]->mFailed) return i; |
569 | } |
570 | return mQueue.Length(); |
571 | } |
572 | |
573 | // SessionCount might be decremented from the main or the socket |
574 | // thread, so manage it with atomic counters |
575 | Atomic<int32_t> mSessionCount; |
576 | |
577 | // Queue for websockets that have not completed connecting yet. |
578 | // The first nsOpenConn with a given address will be either be |
579 | // CONNECTING_IN_PROGRESS or CONNECTING_DELAYED. Later ones with the same |
580 | // hostname must be CONNECTING_QUEUED. |
581 | // |
582 | // We could hash hostnames instead of using a single big vector here, but the |
583 | // dataset is expected to be small. |
584 | nsTArray<UniquePtr<nsOpenConn>> mQueue; |
585 | |
586 | FailDelayManager mFailures; |
587 | |
588 | static nsWSAdmissionManager* sManager MOZ_GUARDED_BY(sLock)__attribute__((guarded_by(sLock))); |
589 | static StaticMutex sLock; |
590 | }; |
591 | |
592 | nsWSAdmissionManager* nsWSAdmissionManager::sManager; |
593 | StaticMutex nsWSAdmissionManager::sLock; |
594 | |
595 | //----------------------------------------------------------------------------- |
596 | // CallOnMessageAvailable |
597 | //----------------------------------------------------------------------------- |
598 | |
599 | class CallOnMessageAvailable final : public Runnable { |
600 | public: |
601 | CallOnMessageAvailable(WebSocketChannel* aChannel, nsACString& aData, |
602 | int32_t aLen) |
603 | : Runnable("net::CallOnMessageAvailable"), |
604 | mChannel(aChannel), |
605 | mListenerMT(aChannel->mListenerMT), |
606 | mData(aData), |
607 | mLen(aLen) {} |
608 | |
609 | NS_IMETHODvirtual nsresult Run() override { |
610 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 610; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
611 | |
612 | if (mListenerMT) { |
613 | nsresult rv; |
614 | if (mLen < 0) { |
615 | rv = mListenerMT->mListener->OnMessageAvailable(mListenerMT->mContext, |
616 | mData); |
617 | } else { |
618 | rv = mListenerMT->mListener->OnBinaryMessageAvailable( |
619 | mListenerMT->mContext, mData); |
620 | } |
621 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
622 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
623 | ("OnMessageAvailable or OnBinaryMessageAvailable "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
624 | "failed with 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
625 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0); |
626 | } |
627 | } |
628 | |
629 | return NS_OK; |
630 | } |
631 | |
632 | private: |
633 | ~CallOnMessageAvailable() = default; |
634 | |
635 | RefPtr<WebSocketChannel> mChannel; |
636 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
637 | nsCString mData; |
638 | int32_t mLen; |
639 | }; |
640 | |
641 | //----------------------------------------------------------------------------- |
642 | // CallOnStop |
643 | //----------------------------------------------------------------------------- |
644 | |
645 | class CallOnStop final : public Runnable { |
646 | public: |
647 | CallOnStop(WebSocketChannel* aChannel, nsresult aReason) |
648 | : Runnable("net::CallOnStop"), |
649 | mChannel(aChannel), |
650 | mListenerMT(mChannel->mListenerMT), |
651 | mReason(aReason) {} |
652 | |
653 | NS_IMETHODvirtual nsresult Run() override { |
654 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 654; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
655 | |
656 | if (mListenerMT) { |
657 | nsresult rv = |
658 | mListenerMT->mListener->OnStop(mListenerMT->mContext, mReason); |
659 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
660 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0) |
661 | ("WebSocketChannel::CallOnStop "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0) |
662 | "OnStop failed (%08" PRIx32 ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0) |
663 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0); |
664 | } |
665 | mChannel->mListenerMT = nullptr; |
666 | } |
667 | |
668 | return NS_OK; |
669 | } |
670 | |
671 | private: |
672 | ~CallOnStop() = default; |
673 | |
674 | RefPtr<WebSocketChannel> mChannel; |
675 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
676 | nsresult mReason; |
677 | }; |
678 | |
679 | //----------------------------------------------------------------------------- |
680 | // CallOnServerClose |
681 | //----------------------------------------------------------------------------- |
682 | |
683 | class CallOnServerClose final : public Runnable { |
684 | public: |
685 | CallOnServerClose(WebSocketChannel* aChannel, uint16_t aCode, |
686 | nsACString& aReason) |
687 | : Runnable("net::CallOnServerClose"), |
688 | mChannel(aChannel), |
689 | mListenerMT(mChannel->mListenerMT), |
690 | mCode(aCode), |
691 | mReason(aReason) {} |
692 | |
693 | NS_IMETHODvirtual nsresult Run() override { |
694 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 694; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
695 | |
696 | if (mListenerMT) { |
697 | nsresult rv = mListenerMT->mListener->OnServerClose(mListenerMT->mContext, |
698 | mCode, mReason); |
699 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
700 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0) |
701 | ("WebSocketChannel::CallOnServerClose "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0) |
702 | "OnServerClose failed (%08" PRIx32 ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0) |
703 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0); |
704 | } |
705 | } |
706 | return NS_OK; |
707 | } |
708 | |
709 | private: |
710 | ~CallOnServerClose() = default; |
711 | |
712 | RefPtr<WebSocketChannel> mChannel; |
713 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
714 | uint16_t mCode; |
715 | nsCString mReason; |
716 | }; |
717 | |
718 | //----------------------------------------------------------------------------- |
719 | // CallAcknowledge |
720 | //----------------------------------------------------------------------------- |
721 | |
722 | class CallAcknowledge final : public Runnable { |
723 | public: |
724 | CallAcknowledge(WebSocketChannel* aChannel, uint32_t aSize) |
725 | : Runnable("net::CallAcknowledge"), |
726 | mChannel(aChannel), |
727 | mListenerMT(mChannel->mListenerMT), |
728 | mSize(aSize) {} |
729 | |
730 | NS_IMETHODvirtual nsresult Run() override { |
731 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 731; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
732 | |
733 | LOG(("WebSocketChannel::CallAcknowledge: Size %u\n", mSize))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Size %u\n" , mSize); } } while (0); |
734 | if (mListenerMT) { |
735 | nsresult rv = |
736 | mListenerMT->mListener->OnAcknowledge(mListenerMT->mContext, mSize); |
737 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
738 | LOG(("WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" "x" ")\n", static_cast<uint32_t>(rv)); } } while (0) |
739 | ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" "x" ")\n", static_cast<uint32_t>(rv)); } } while (0) |
740 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" "x" ")\n", static_cast<uint32_t>(rv)); } } while (0); |
741 | } |
742 | } |
743 | return NS_OK; |
744 | } |
745 | |
746 | private: |
747 | ~CallAcknowledge() = default; |
748 | |
749 | RefPtr<WebSocketChannel> mChannel; |
750 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
751 | uint32_t mSize; |
752 | }; |
753 | |
754 | //----------------------------------------------------------------------------- |
755 | // CallOnTransportAvailable |
756 | //----------------------------------------------------------------------------- |
757 | |
758 | class CallOnTransportAvailable final : public Runnable { |
759 | public: |
760 | CallOnTransportAvailable(WebSocketChannel* aChannel, |
761 | nsISocketTransport* aTransport, |
762 | nsIAsyncInputStream* aSocketIn, |
763 | nsIAsyncOutputStream* aSocketOut) |
764 | : Runnable("net::CallOnTransportAvailble"), |
765 | mChannel(aChannel), |
766 | mTransport(aTransport), |
767 | mSocketIn(aSocketIn), |
768 | mSocketOut(aSocketOut) {} |
769 | |
770 | NS_IMETHODvirtual nsresult Run() override { |
771 | LOG(("WebSocketChannel::CallOnTransportAvailable %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnTransportAvailable %p\n" , this); } } while (0); |
772 | return mChannel->OnTransportAvailable(mTransport, mSocketIn, mSocketOut); |
773 | } |
774 | |
775 | private: |
776 | ~CallOnTransportAvailable() = default; |
777 | |
778 | RefPtr<WebSocketChannel> mChannel; |
779 | nsCOMPtr<nsISocketTransport> mTransport; |
780 | nsCOMPtr<nsIAsyncInputStream> mSocketIn; |
781 | nsCOMPtr<nsIAsyncOutputStream> mSocketOut; |
782 | }; |
783 | |
784 | //----------------------------------------------------------------------------- |
785 | // PMCECompression |
786 | //----------------------------------------------------------------------------- |
787 | |
788 | class PMCECompression { |
789 | public: |
790 | PMCECompression(bool aNoContextTakeover, int32_t aLocalMaxWindowBits, |
791 | int32_t aRemoteMaxWindowBits) |
792 | : mActive(false), |
793 | mNoContextTakeover(aNoContextTakeover), |
794 | mResetDeflater(false), |
795 | mMessageDeflated(false) { |
796 | this->mDeflater.next_in = nullptr; |
797 | this->mDeflater.avail_in = 0; |
798 | this->mDeflater.total_in = 0; |
799 | this->mDeflater.next_out = nullptr; |
800 | this->mDeflater.avail_out = 0; |
801 | this->mDeflater.total_out = 0; |
802 | this->mDeflater.msg = nullptr; |
803 | this->mDeflater.state = nullptr; |
804 | this->mDeflater.data_type = 0; |
805 | this->mDeflater.adler = 0; |
806 | this->mDeflater.reserved = 0; |
807 | this->mInflater.next_in = nullptr; |
808 | this->mInflater.avail_in = 0; |
809 | this->mInflater.total_in = 0; |
810 | this->mInflater.next_out = nullptr; |
811 | this->mInflater.avail_out = 0; |
812 | this->mInflater.total_out = 0; |
813 | this->mInflater.msg = nullptr; |
814 | this->mInflater.state = nullptr; |
815 | this->mInflater.data_type = 0; |
816 | this->mInflater.adler = 0; |
817 | this->mInflater.reserved = 0; |
818 | MOZ_COUNT_CTOR(PMCECompression)do { static_assert(std::is_class_v<PMCECompression>, "Token '" "PMCECompression" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, PMCECompression>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "PMCECompression" , sizeof(*this)); } while (0); |
819 | |
820 | mDeflater.zalloc = mInflater.zalloc = Z_NULL0; |
821 | mDeflater.zfree = mInflater.zfree = Z_NULL0; |
822 | mDeflater.opaque = mInflater.opaque = Z_NULL0; |
823 | |
824 | if (deflateInit2(&mDeflater, Z_DEFAULT_COMPRESSION, Z_DEFLATED,MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits ),(8), (0), "1.3.1", (int)sizeof(z_stream)) |
825 | -aLocalMaxWindowBits, 8, Z_DEFAULT_STRATEGY)MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits ),(8), (0), "1.3.1", (int)sizeof(z_stream)) == Z_OK0) { |
826 | if (inflateInit2(&mInflater, -aRemoteMaxWindowBits)MOZ_Z_inflateInit2_((&mInflater), (-aRemoteMaxWindowBits) , "1.3.1", (int)sizeof(z_stream)) == Z_OK0) { |
827 | mActive = true; |
828 | } else { |
829 | deflateEndMOZ_Z_deflateEnd(&mDeflater); |
830 | } |
831 | } |
832 | } |
833 | |
834 | ~PMCECompression() { |
835 | MOZ_COUNT_DTOR(PMCECompression)do { static_assert(std::is_class_v<PMCECompression>, "Token '" "PMCECompression" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, PMCECompression>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "PMCECompression" , sizeof(*this)); } while (0); |
836 | |
837 | if (mActive) { |
838 | inflateEndMOZ_Z_inflateEnd(&mInflater); |
839 | deflateEndMOZ_Z_deflateEnd(&mDeflater); |
840 | } |
841 | } |
842 | |
843 | bool Active() { return mActive; } |
844 | |
845 | void SetMessageDeflated() { |
846 | MOZ_ASSERT(!mMessageDeflated)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mMessageDeflated)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mMessageDeflated))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mMessageDeflated" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mMessageDeflated" ")"); do { *((volatile int*)__null) = 846; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
847 | mMessageDeflated = true; |
848 | } |
849 | bool IsMessageDeflated() { return mMessageDeflated; } |
850 | |
851 | bool UsingContextTakeover() { return !mNoContextTakeover; } |
852 | |
853 | nsresult Deflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) { |
854 | if (mResetDeflater || mNoContextTakeover) { |
855 | if (deflateResetMOZ_Z_deflateReset(&mDeflater) != Z_OK0) { |
856 | return NS_ERROR_UNEXPECTED; |
857 | } |
858 | mResetDeflater = false; |
859 | } |
860 | |
861 | mDeflater.avail_out = kBufferLen; |
862 | mDeflater.next_out = mBuffer; |
863 | mDeflater.avail_in = dataLen; |
864 | mDeflater.next_in = data; |
865 | |
866 | while (true) { |
867 | int zerr = deflateMOZ_Z_deflate(&mDeflater, Z_SYNC_FLUSH2); |
868 | |
869 | if (zerr != Z_OK0) { |
870 | mResetDeflater = true; |
871 | return NS_ERROR_UNEXPECTED; |
872 | } |
873 | |
874 | uint32_t deflated = kBufferLen - mDeflater.avail_out; |
875 | if (deflated > 0) { |
876 | _retval.Append(reinterpret_cast<char*>(mBuffer), deflated); |
877 | } |
878 | |
879 | mDeflater.avail_out = kBufferLen; |
880 | mDeflater.next_out = mBuffer; |
881 | |
882 | if (mDeflater.avail_in > 0) { |
883 | continue; // There is still some data to deflate |
884 | } |
885 | |
886 | if (deflated == kBufferLen) { |
887 | continue; // There was not enough space in the buffer |
888 | } |
889 | |
890 | break; |
891 | } |
892 | |
893 | if (_retval.Length() < 4) { |
894 | MOZ_ASSERT(false, "Expected trailing not found in deflated data!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Expected trailing not found in deflated data!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Expected trailing not found in deflated data!" ")"); do { * ((volatile int*)__null) = 894; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
895 | mResetDeflater = true; |
896 | return NS_ERROR_UNEXPECTED; |
897 | } |
898 | |
899 | _retval.Truncate(_retval.Length() - 4); |
900 | |
901 | return NS_OK; |
902 | } |
903 | |
904 | nsresult Inflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) { |
905 | mMessageDeflated = false; |
906 | |
907 | Bytef trailingData[] = {0x00, 0x00, 0xFF, 0xFF}; |
908 | bool trailingDataUsed = false; |
909 | |
910 | mInflater.avail_out = kBufferLen; |
911 | mInflater.next_out = mBuffer; |
912 | mInflater.avail_in = dataLen; |
913 | mInflater.next_in = data; |
914 | |
915 | while (true) { |
916 | int zerr = inflateMOZ_Z_inflate(&mInflater, Z_NO_FLUSH0); |
917 | |
918 | if (zerr == Z_STREAM_END1) { |
919 | Bytef* saveNextIn = mInflater.next_in; |
920 | uint32_t saveAvailIn = mInflater.avail_in; |
921 | Bytef* saveNextOut = mInflater.next_out; |
922 | uint32_t saveAvailOut = mInflater.avail_out; |
923 | |
924 | inflateResetMOZ_Z_inflateReset(&mInflater); |
925 | |
926 | mInflater.next_in = saveNextIn; |
927 | mInflater.avail_in = saveAvailIn; |
928 | mInflater.next_out = saveNextOut; |
929 | mInflater.avail_out = saveAvailOut; |
930 | } else if (zerr != Z_OK0 && zerr != Z_BUF_ERROR(-5)) { |
931 | return NS_ERROR_INVALID_CONTENT_ENCODING; |
932 | } |
933 | |
934 | uint32_t inflated = kBufferLen - mInflater.avail_out; |
935 | if (inflated > 0) { |
936 | if (!_retval.Append(reinterpret_cast<char*>(mBuffer), inflated, |
937 | fallible)) { |
938 | return NS_ERROR_OUT_OF_MEMORY; |
939 | } |
940 | } |
941 | |
942 | mInflater.avail_out = kBufferLen; |
943 | mInflater.next_out = mBuffer; |
944 | |
945 | if (mInflater.avail_in > 0) { |
946 | continue; // There is still some data to inflate |
947 | } |
948 | |
949 | if (inflated == kBufferLen) { |
950 | continue; // There was not enough space in the buffer |
951 | } |
952 | |
953 | if (!trailingDataUsed) { |
954 | trailingDataUsed = true; |
955 | mInflater.avail_in = sizeof(trailingData); |
956 | mInflater.next_in = trailingData; |
957 | continue; |
958 | } |
959 | |
960 | return NS_OK; |
961 | } |
962 | } |
963 | |
964 | private: |
965 | bool mActive; |
966 | bool mNoContextTakeover; |
967 | bool mResetDeflater; |
968 | bool mMessageDeflated; |
969 | z_stream mDeflater{}; |
970 | z_stream mInflater{}; |
971 | const static uint32_t kBufferLen = 4096; |
972 | uint8_t mBuffer[kBufferLen]{0}; |
973 | }; |
974 | |
975 | //----------------------------------------------------------------------------- |
976 | // OutboundMessage |
977 | //----------------------------------------------------------------------------- |
978 | |
979 | enum WsMsgType { |
980 | kMsgTypeString = 0, |
981 | kMsgTypeBinaryString, |
982 | kMsgTypeStream, |
983 | kMsgTypePing, |
984 | kMsgTypePong, |
985 | kMsgTypeFin |
986 | }; |
987 | |
988 | static const char* msgNames[] = {"text", "binaryString", "binaryStream", |
989 | "ping", "pong", "close"}; |
990 | |
991 | class OutboundMessage { |
992 | public: |
993 | OutboundMessage(WsMsgType type, const nsACString& str) |
994 | : mMsg(mozilla::AsVariant(pString(str))), |
995 | mMsgType(type), |
996 | mDeflated(false) { |
997 | MOZ_COUNT_CTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '" "OutboundMessage" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "OutboundMessage" , sizeof(*this)); } while (0); |
998 | } |
999 | |
1000 | OutboundMessage(nsIInputStream* stream, uint32_t length) |
1001 | : mMsg(mozilla::AsVariant(StreamWithLength(stream, length))), |
1002 | mMsgType(kMsgTypeStream), |
1003 | mDeflated(false) { |
1004 | MOZ_COUNT_CTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '" "OutboundMessage" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "OutboundMessage" , sizeof(*this)); } while (0); |
1005 | } |
1006 | |
1007 | ~OutboundMessage() { |
1008 | MOZ_COUNT_DTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '" "OutboundMessage" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "OutboundMessage" , sizeof(*this)); } while (0); |
1009 | switch (mMsgType) { |
1010 | case kMsgTypeString: |
1011 | case kMsgTypeBinaryString: |
1012 | case kMsgTypePing: |
1013 | case kMsgTypePong: |
1014 | break; |
1015 | case kMsgTypeStream: |
1016 | // for now this only gets hit if msg deleted w/o being sent |
1017 | if (mMsg.as<StreamWithLength>().mStream) { |
1018 | mMsg.as<StreamWithLength>().mStream->Close(); |
1019 | } |
1020 | break; |
1021 | case kMsgTypeFin: |
1022 | break; // do-nothing: avoid compiler warning |
1023 | } |
1024 | } |
1025 | |
1026 | WsMsgType GetMsgType() const { return mMsgType; } |
1027 | int32_t Length() { |
1028 | if (mMsg.is<pString>()) { |
1029 | return mMsg.as<pString>().mValue.Length(); |
1030 | } |
1031 | |
1032 | return mMsg.as<StreamWithLength>().mLength; |
1033 | } |
1034 | int32_t OrigLength() { |
1035 | if (mMsg.is<pString>()) { |
1036 | pString& ref = mMsg.as<pString>(); |
1037 | return mDeflated ? ref.mOrigValue.Length() : ref.mValue.Length(); |
1038 | } |
1039 | |
1040 | return mMsg.as<StreamWithLength>().mLength; |
1041 | } |
1042 | |
1043 | uint8_t* BeginWriting() { |
1044 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1045; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1045 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1045; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1046 | if (!mMsg.as<pString>().mValue.IsVoid()) { |
1047 | return (uint8_t*)mMsg.as<pString>().mValue.BeginWriting(); |
1048 | } |
1049 | return nullptr; |
1050 | } |
1051 | |
1052 | uint8_t* BeginReading() { |
1053 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1054; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1054 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1054; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1055 | if (!mMsg.as<pString>().mValue.IsVoid()) { |
1056 | return (uint8_t*)mMsg.as<pString>().mValue.BeginReading(); |
1057 | } |
1058 | return nullptr; |
1059 | } |
1060 | |
1061 | uint8_t* BeginOrigReading() { |
1062 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1063; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1063 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1063; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1064 | if (!mDeflated) return BeginReading(); |
1065 | if (!mMsg.as<pString>().mOrigValue.IsVoid()) { |
1066 | return (uint8_t*)mMsg.as<pString>().mOrigValue.BeginReading(); |
1067 | } |
1068 | return nullptr; |
1069 | } |
1070 | |
1071 | nsresult ConvertStreamToString() { |
1072 | MOZ_ASSERT(mMsgType == kMsgTypeStream, "Not a stream!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType == kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType == kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType == kMsgTypeStream" " (" "Not a stream!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType == kMsgTypeStream" ") (" "Not a stream!" ")"); do { *((volatile int*)__null) = 1072 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1073 | nsAutoCString temp; |
1074 | { |
1075 | StreamWithLength& ref = mMsg.as<StreamWithLength>(); |
1076 | nsresult rv = NS_ReadInputStreamToString(ref.mStream, temp, ref.mLength); |
1077 | |
1078 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1078); return rv; } } while (false); |
1079 | if (temp.Length() != ref.mLength) { |
1080 | return NS_ERROR_UNEXPECTED; |
1081 | } |
1082 | ref.mStream->Close(); |
1083 | } |
1084 | |
1085 | mMsg = mozilla::AsVariant(pString(temp)); |
1086 | mMsgType = kMsgTypeBinaryString; |
1087 | |
1088 | return NS_OK; |
1089 | } |
1090 | |
1091 | bool DeflatePayload(PMCECompression* aCompressor) { |
1092 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1093; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1093 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1093; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1094 | MOZ_ASSERT(!mDeflated)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeflated)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeflated))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeflated", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDeflated" ")"); do { *((volatile int*)__null) = 1094; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1095 | |
1096 | nsresult rv; |
1097 | pString& ref = mMsg.as<pString>(); |
1098 | if (ref.mValue.Length() == 0) { |
1099 | // Empty message |
1100 | return false; |
1101 | } |
1102 | |
1103 | nsAutoCString temp; |
1104 | rv = aCompressor->Deflate(BeginReading(), ref.mValue.Length(), temp); |
1105 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1106 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0) |
1107 | ("WebSocketChannel::OutboundMessage: Deflating payload failed "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0) |
1108 | "[rv=0x%08" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0) |
1109 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0); |
1110 | return false; |
1111 | } |
1112 | |
1113 | if (!aCompressor->UsingContextTakeover() && |
1114 | temp.Length() > ref.mValue.Length()) { |
1115 | // When "<local>_no_context_takeover" was negotiated, do not send deflated |
1116 | // payload if it's larger that the original one. OTOH, it makes sense |
1117 | // to send the larger deflated payload when the sliding window is not |
1118 | // reset between messages because if we would skip some deflated block |
1119 | // we would need to empty the sliding window which could affect the |
1120 | // compression of the subsequent messages. |
1121 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1122 | ("WebSocketChannel::OutboundMessage: Not deflating message since the "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1123 | "deflated payload is larger than the original one [deflated=%zd, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1124 | "original=%zd]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1125 | temp.Length(), ref.mValue.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0); |
1126 | return false; |
1127 | } |
1128 | |
1129 | mDeflated = true; |
1130 | mMsg.as<pString>().mOrigValue = mMsg.as<pString>().mValue; |
1131 | mMsg.as<pString>().mValue = temp; |
1132 | return true; |
1133 | } |
1134 | |
1135 | private: |
1136 | struct pString { |
1137 | nsCString mValue; |
1138 | nsCString mOrigValue; |
1139 | explicit pString(const nsACString& value) |
1140 | : mValue(value), mOrigValue(VoidCString()) {} |
1141 | }; |
1142 | struct StreamWithLength { |
1143 | nsCOMPtr<nsIInputStream> mStream; |
1144 | uint32_t mLength; |
1145 | explicit StreamWithLength(nsIInputStream* stream, uint32_t Length) |
1146 | : mStream(stream), mLength(Length) {} |
1147 | }; |
1148 | mozilla::Variant<pString, StreamWithLength> mMsg; |
1149 | WsMsgType mMsgType; |
1150 | bool mDeflated; |
1151 | }; |
1152 | |
1153 | //----------------------------------------------------------------------------- |
1154 | // OutboundEnqueuer |
1155 | //----------------------------------------------------------------------------- |
1156 | |
1157 | class OutboundEnqueuer final : public Runnable { |
1158 | public: |
1159 | OutboundEnqueuer(WebSocketChannel* aChannel, OutboundMessage* aMsg) |
1160 | : Runnable("OutboundEnquerer"), mChannel(aChannel), mMessage(aMsg) {} |
1161 | |
1162 | NS_IMETHODvirtual nsresult Run() override { |
1163 | mChannel->EnqueueOutgoingMessage(mChannel->mOutgoingMessages, mMessage); |
1164 | return NS_OK; |
1165 | } |
1166 | |
1167 | private: |
1168 | ~OutboundEnqueuer() = default; |
1169 | |
1170 | RefPtr<WebSocketChannel> mChannel; |
1171 | OutboundMessage* mMessage; |
1172 | }; |
1173 | |
1174 | //----------------------------------------------------------------------------- |
1175 | // WebSocketChannel |
1176 | //----------------------------------------------------------------------------- |
1177 | |
1178 | WebSocketChannel::WebSocketChannel() |
1179 | : mPort(0), |
1180 | mCloseTimeout(20000), |
1181 | mOpenTimeout(20000), |
1182 | mConnecting(NOT_CONNECTING), |
1183 | mMaxConcurrentConnections(200), |
1184 | mInnerWindowID(0), |
1185 | mGotUpgradeOK(0), |
1186 | mRecvdHttpUpgradeTransport(0), |
1187 | mPingOutstanding(0), |
1188 | mReleaseOnTransmit(0), |
1189 | mDataStarted(false), |
1190 | mRequestedClose(false), |
1191 | mClientClosed(false), |
1192 | mServerClosed(false), |
1193 | mStopped(false), |
1194 | mCalledOnStop(false), |
1195 | mTCPClosed(false), |
1196 | mOpenedHttpChannel(false), |
1197 | mIncrementedSessionCount(false), |
1198 | mDecrementedSessionCount(false), |
1199 | mMaxMessageSize(INT32_MAX(2147483647)), |
1200 | mStopOnClose(NS_OK), |
1201 | mServerCloseCode(CLOSE_ABNORMAL), |
1202 | mScriptCloseCode(0), |
1203 | mFragmentOpcode(nsIWebSocketFrame::OPCODE_CONTINUATION), |
1204 | mFragmentAccumulator(0), |
1205 | mBuffered(0), |
1206 | mBufferSize(kIncomingBufferInitialSize), |
1207 | mCurrentOut(nullptr), |
1208 | mCurrentOutSent(0), |
1209 | mHdrOutToSend(0), |
1210 | mHdrOut(nullptr), |
1211 | mCompressorMutex("WebSocketChannel::mCompressorMutex"), |
1212 | mDynamicOutputSize(0), |
1213 | mDynamicOutput(nullptr), |
1214 | mPrivateBrowsing(false), |
1215 | mConnectionLogService(nullptr), |
1216 | mMutex("WebSocketChannel::mMutex") { |
1217 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1217; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1218 | |
1219 | LOG(("WebSocketChannel::WebSocketChannel() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::WebSocketChannel() %p\n" , this); } } while (0); |
1220 | |
1221 | nsWSAdmissionManager::Init(); |
1222 | |
1223 | mFramePtr = mBuffer = static_cast<uint8_t*>(moz_xmalloc(mBufferSize)); |
1224 | |
1225 | nsresult rv; |
1226 | mConnectionLogService = mozilla::components::Dashboard::Service(&rv); |
1227 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) LOG(("Failed to initiate dashboard service."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Failed to initiate dashboard service." ); } } while (0); |
1228 | |
1229 | mService = WebSocketEventService::GetOrCreate(); |
1230 | } |
1231 | |
1232 | WebSocketChannel::~WebSocketChannel() { |
1233 | LOG(("WebSocketChannel::~WebSocketChannel() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::~WebSocketChannel() %p\n" , this); } } while (0); |
1234 | |
1235 | if (mWasOpened) { |
1236 | MOZ_ASSERT(mCalledOnStop, "WebSocket was opened but OnStop was not called")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCalledOnStop)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mCalledOnStop))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCalledOnStop" " (" "WebSocket was opened but OnStop was not called" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCalledOnStop" ") (" "WebSocket was opened but OnStop was not called" ")"); do { *((volatile int*)__null) = 1236; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1237 | MOZ_ASSERT(mStopped, "WebSocket was opened but never stopped")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped" " (" "WebSocket was opened but never stopped" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") (" "WebSocket was opened but never stopped" ")"); do { *((volatile int*)__null) = 1237; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1238 | } |
1239 | MOZ_ASSERT(!mCancelable, "DNS/Proxy Request still alive at destruction")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable" " (" "DNS/Proxy Request still alive at destruction" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ") (" "DNS/Proxy Request still alive at destruction" ")"); do { *((volatile int*)__null) = 1239; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
1240 | MOZ_ASSERT(!mConnecting, "Should not be connecting in destructor")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mConnecting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mConnecting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mConnecting" " (" "Should not be connecting in destructor" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnecting" ") (" "Should not be connecting in destructor" ")"); do { *( (volatile int*)__null) = 1240; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
1241 | |
1242 | free(mBuffer); |
1243 | free(mDynamicOutput); |
1244 | delete mCurrentOut; |
1245 | |
1246 | while ((mCurrentOut = mOutgoingPingMessages.PopFront())) { |
1247 | delete mCurrentOut; |
1248 | } |
1249 | while ((mCurrentOut = mOutgoingPongMessages.PopFront())) { |
1250 | delete mCurrentOut; |
1251 | } |
1252 | while ((mCurrentOut = mOutgoingMessages.PopFront())) { |
1253 | delete mCurrentOut; |
1254 | } |
1255 | |
1256 | mListenerMT = nullptr; |
1257 | |
1258 | NS_ReleaseOnMainThread("WebSocketChannel::mService", mService.forget()); |
1259 | } |
1260 | |
1261 | NS_IMETHODIMPnsresult |
1262 | WebSocketChannel::Observe(nsISupports* subject, const char* topic, |
1263 | const char16_t* data) { |
1264 | LOG(("WebSocketChannel::Observe [topic=\"%s\"]\n", topic))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Observe [topic=\"%s\"]\n" , topic); } } while (0); |
1265 | |
1266 | if (strcmp(topic, NS_NETWORK_LINK_TOPIC"network:link-status-changed") == 0) { |
1267 | nsCString converted = NS_ConvertUTF16toUTF8(data); |
1268 | const char* state = converted.get(); |
1269 | |
1270 | if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED"changed") == 0) { |
1271 | LOG(("WebSocket: received network CHANGED event"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: received network CHANGED event" ); } } while (0); |
1272 | |
1273 | if (!mIOThread) { |
1274 | // there has not been an asyncopen yet on the object and then we need |
1275 | // no ping. |
1276 | LOG(("WebSocket: early object, no ping needed"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: early object, no ping needed" ); } } while (0); |
1277 | } else { |
1278 | mIOThread->Dispatch( |
1279 | NewRunnableMethod("net::WebSocketChannel::OnNetworkChanged", this, |
1280 | &WebSocketChannel::OnNetworkChanged), |
1281 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1282 | } |
1283 | } |
1284 | } |
1285 | |
1286 | return NS_OK; |
1287 | } |
1288 | |
1289 | nsresult WebSocketChannel::OnNetworkChanged() { |
1290 | if (!mDataStarted) { |
1291 | LOG(("WebSocket: data not started yet, no ping needed"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: data not started yet, no ping needed" ); } } while (0); |
1292 | return NS_OK; |
1293 | } |
1294 | |
1295 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1295; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1296 | |
1297 | LOG(("WebSocketChannel::OnNetworkChanged() - on socket thread %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnNetworkChanged() - on socket thread %p" , this); } } while (0); |
1298 | |
1299 | if (mPingOutstanding) { |
1300 | // If there's an outstanding ping that's expected to get a pong back |
1301 | // we let that do its thing. |
1302 | LOG(("WebSocket: pong already pending"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: pong already pending" ); } } while (0); |
1303 | return NS_OK; |
1304 | } |
1305 | |
1306 | if (mPingForced) { |
1307 | // avoid more than one |
1308 | LOG(("WebSocket: forced ping timer already fired"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: forced ping timer already fired" ); } } while (0); |
1309 | return NS_OK; |
1310 | } |
1311 | |
1312 | LOG(("nsWebSocketChannel:: Generating Ping as network changed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Generating Ping as network changed\n" ); } } while (0); |
1313 | |
1314 | if (!mPingTimer) { |
1315 | // The ping timer is only conditionally running already. If it wasn't |
1316 | // already created do it here. |
1317 | mPingTimer = NS_NewTimer(); |
1318 | if (!mPingTimer) { |
1319 | LOG(("WebSocket: unable to create ping timer!"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: unable to create ping timer!" ); } } while (0); |
1320 | NS_WARNING("unable to create ping timer!")NS_DebugBreak(NS_DEBUG_WARNING, "unable to create ping timer!" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1320); |
1321 | return NS_ERROR_OUT_OF_MEMORY; |
1322 | } |
1323 | } |
1324 | // Trigger the ping timeout asap to fire off a new ping. Wait just |
1325 | // a little bit to better avoid multi-triggers. |
1326 | mPingForced = true; |
1327 | mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT); |
1328 | |
1329 | return NS_OK; |
1330 | } |
1331 | |
1332 | void WebSocketChannel::Shutdown() { nsWSAdmissionManager::Shutdown(); } |
1333 | |
1334 | void WebSocketChannel::GetEffectiveURL(nsAString& aEffectiveURL) const { |
1335 | aEffectiveURL = mEffectiveURL; |
1336 | } |
1337 | |
1338 | bool WebSocketChannel::IsEncrypted() const { return mEncrypted; } |
1339 | |
1340 | void WebSocketChannel::BeginOpen(bool aCalledFromAdmissionManager) { |
1341 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1341; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1342 | |
1343 | LOG(("WebSocketChannel::BeginOpen() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpen() %p\n" , this); } } while (0); |
1344 | |
1345 | // Important that we set CONNECTING_IN_PROGRESS before any call to |
1346 | // AbortSession here: ensures that any remaining queued connection(s) are |
1347 | // scheduled in OnStopSession |
1348 | LOG(("Websocket: changing state to CONNECTING_IN_PROGRESS"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to CONNECTING_IN_PROGRESS" ); } } while (0); |
1349 | mConnecting = CONNECTING_IN_PROGRESS; |
1350 | |
1351 | if (aCalledFromAdmissionManager) { |
1352 | // When called from nsWSAdmissionManager post an event to avoid potential |
1353 | // re-entering of nsWSAdmissionManager and its lock. |
1354 | NS_DispatchToMainThread( |
1355 | NewRunnableMethod("net::WebSocketChannel::BeginOpenInternal", this, |
1356 | &WebSocketChannel::BeginOpenInternal), |
1357 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1358 | } else { |
1359 | BeginOpenInternal(); |
1360 | } |
1361 | } |
1362 | |
1363 | // MainThread |
1364 | void WebSocketChannel::BeginOpenInternal() { |
1365 | LOG(("WebSocketChannel::BeginOpenInternal() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal() %p\n" , this); } } while (0); |
1366 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1366; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1367 | |
1368 | nsresult rv; |
1369 | |
1370 | if (mRedirectCallback) { |
1371 | LOG(("WebSocketChannel::BeginOpenInternal: Resuming Redirect\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: Resuming Redirect\n" ); } } while (0); |
1372 | rv = mRedirectCallback->OnRedirectVerifyCallback(NS_OK); |
1373 | mRedirectCallback = nullptr; |
1374 | return; |
1375 | } |
1376 | |
1377 | nsCOMPtr<nsIChannel> localChannel = do_QueryInterface(mChannel, &rv); |
1378 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1379 | LOG(("WebSocketChannel::BeginOpenInternal: cannot async open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot async open\n" ); } } while (0); |
1380 | AbortSession(NS_ERROR_UNEXPECTED); |
1381 | return; |
1382 | } |
1383 | |
1384 | rv = localChannel->AsyncOpen(this); |
1385 | |
1386 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1387 | LOG(("WebSocketChannel::BeginOpenInternal: cannot async open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot async open\n" ); } } while (0); |
1388 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
1389 | return; |
1390 | } |
1391 | mOpenedHttpChannel = true; |
1392 | |
1393 | rv = NS_NewTimerWithCallback(getter_AddRefs(mOpenTimer), this, mOpenTimeout, |
1394 | nsITimer::TYPE_ONE_SHOT); |
1395 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1396 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open " "timer\n"); } } while (0) |
1397 | ("WebSocketChannel::BeginOpenInternal: cannot initialize open "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open " "timer\n"); } } while (0) |
1398 | "timer\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open " "timer\n"); } } while (0); |
1399 | AbortSession(NS_ERROR_UNEXPECTED); |
1400 | return; |
1401 | } |
1402 | } |
1403 | |
1404 | bool WebSocketChannel::IsPersistentFramePtr() { |
1405 | return (mFramePtr >= mBuffer && mFramePtr < mBuffer + mBufferSize); |
1406 | } |
1407 | |
1408 | // Extends the internal buffer by count and returns the total |
1409 | // amount of data available for read |
1410 | // |
1411 | // Accumulated fragment size is passed in instead of using the member |
1412 | // variable beacuse when transitioning from the stack to the persistent |
1413 | // read buffer we want to explicitly include them in the buffer instead |
1414 | // of as already existing data. |
1415 | bool WebSocketChannel::UpdateReadBuffer(uint8_t* buffer, uint32_t count, |
1416 | uint32_t accumulatedFragments, |
1417 | uint32_t* available) { |
1418 | LOG(("WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n", this, buffer,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n" , this, buffer, count); } } while (0) |
1419 | count))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n" , this, buffer, count); } } while (0); |
1420 | |
1421 | if (!mBuffered) mFramePtr = mBuffer; |
1422 | |
1423 | MOZ_ASSERT(IsPersistentFramePtr(), "update read buffer bad mFramePtr")do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPersistentFramePtr())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsPersistentFramePtr()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("IsPersistentFramePtr()" " (" "update read buffer bad mFramePtr" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPersistentFramePtr()" ") (" "update read buffer bad mFramePtr" ")"); do { *((volatile int*)__null) = 1423; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1424 | MOZ_ASSERT(mFramePtr - accumulatedFragments >= mBuffer,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr - accumulatedFragments >= mBuffer)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mFramePtr - accumulatedFragments >= mBuffer))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("mFramePtr - accumulatedFragments >= mBuffer" " (" "reserved FramePtr bad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer" ") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null ) = 1425; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
1425 | "reserved FramePtr bad")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr - accumulatedFragments >= mBuffer)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mFramePtr - accumulatedFragments >= mBuffer))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("mFramePtr - accumulatedFragments >= mBuffer" " (" "reserved FramePtr bad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer" ") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null ) = 1425; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1426 | |
1427 | if (mBuffered + count <= mBufferSize) { |
1428 | // append to existing buffer |
1429 | LOG(("WebSocketChannel: update read buffer absorbed %u\n", count))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer absorbed %u\n" , count); } } while (0); |
1430 | } else if (mBuffered + count - (mFramePtr - accumulatedFragments - mBuffer) <= |
1431 | mBufferSize) { |
1432 | // make room in existing buffer by shifting unused data to start |
1433 | mBuffered -= (mFramePtr - mBuffer - accumulatedFragments); |
1434 | LOG(("WebSocketChannel: update read buffer shifted %u\n", mBuffered))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer shifted %u\n" , mBuffered); } } while (0); |
1435 | ::memmove(mBuffer, mFramePtr - accumulatedFragments, mBuffered); |
1436 | mFramePtr = mBuffer + accumulatedFragments; |
1437 | } else { |
1438 | // existing buffer is not sufficient, extend it |
1439 | mBufferSize += count + 8192 + mBufferSize / 3; |
1440 | LOG(("WebSocketChannel: update read buffer extended to %u\n", mBufferSize))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer extended to %u\n" , mBufferSize); } } while (0); |
1441 | uint8_t* old = mBuffer; |
1442 | mBuffer = (uint8_t*)realloc(mBuffer, mBufferSize); |
1443 | if (!mBuffer) { |
1444 | mBuffer = old; |
1445 | return false; |
1446 | } |
1447 | mFramePtr = mBuffer + (mFramePtr - old); |
1448 | } |
1449 | |
1450 | ::memcpy(mBuffer + mBuffered, buffer, count); |
1451 | mBuffered += count; |
1452 | |
1453 | if (available) *available = mBuffered - (mFramePtr - mBuffer); |
1454 | |
1455 | return true; |
1456 | } |
1457 | |
1458 | nsresult WebSocketChannel::ProcessInput(uint8_t* buffer, uint32_t count) { |
1459 | LOG(("WebSocketChannel::ProcessInput %p [%d %d]\n", this, count, mBuffered))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput %p [%d %d]\n" , this, count, mBuffered); } } while (0); |
1460 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1460; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1461 | |
1462 | nsresult rv; |
1463 | |
1464 | // The purpose of ping/pong is to actively probe the peer so that an |
1465 | // unreachable peer is not mistaken for a period of idleness. This |
1466 | // implementation accepts any application level read activity as a sign of |
1467 | // life, it does not necessarily have to be a pong. |
1468 | ResetPingTimer(); |
1469 | |
1470 | uint32_t avail; |
1471 | |
1472 | if (!mBuffered) { |
1473 | // Most of the time we can process right off the stack buffer without |
1474 | // having to accumulate anything |
1475 | mFramePtr = buffer; |
1476 | avail = count; |
1477 | } else { |
1478 | if (!UpdateReadBuffer(buffer, count, mFragmentAccumulator, &avail)) { |
1479 | return NS_ERROR_FILE_TOO_BIG; |
1480 | } |
1481 | } |
1482 | |
1483 | uint8_t* payload; |
1484 | uint32_t totalAvail = avail; |
1485 | |
1486 | while (avail >= 2) { |
1487 | int64_t payloadLength64 = mFramePtr[1] & kPayloadLengthBitsMask; |
1488 | uint8_t finBit = mFramePtr[0] & kFinalFragBit; |
1489 | uint8_t rsvBits = mFramePtr[0] & kRsvBitsMask; |
1490 | uint8_t rsvBit1 = mFramePtr[0] & kRsv1Bit; |
1491 | uint8_t rsvBit2 = mFramePtr[0] & kRsv2Bit; |
1492 | uint8_t rsvBit3 = mFramePtr[0] & kRsv3Bit; |
1493 | uint8_t opcode = mFramePtr[0] & kOpcodeBitsMask; |
1494 | uint8_t maskBit = mFramePtr[1] & kMaskBit; |
1495 | uint32_t mask = 0; |
1496 | |
1497 | uint32_t framingLength = 2; |
1498 | if (maskBit) framingLength += 4; |
1499 | |
1500 | if (payloadLength64 < 126) { |
1501 | if (avail < framingLength) break; |
1502 | } else if (payloadLength64 == 126) { |
1503 | // 16 bit length field |
1504 | framingLength += 2; |
1505 | if (avail < framingLength) break; |
1506 | |
1507 | payloadLength64 = mFramePtr[2] << 8 | mFramePtr[3]; |
1508 | |
1509 | if (payloadLength64 < 126) { |
1510 | // Section 5.2 says that the minimal number of bytes MUST |
1511 | // be used to encode the length in all cases |
1512 | LOG(("WebSocketChannel:: non-minimal-encoded payload length"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: non-minimal-encoded payload length" ); } } while (0); |
1513 | return NS_ERROR_ILLEGAL_VALUE; |
1514 | } |
1515 | |
1516 | } else { |
1517 | // 64 bit length |
1518 | framingLength += 8; |
1519 | if (avail < framingLength) break; |
1520 | |
1521 | if (mFramePtr[2] & 0x80) { |
1522 | // Section 4.2 says that the most significant bit MUST be |
1523 | // 0. (i.e. this is really a 63 bit value) |
1524 | LOG(("WebSocketChannel:: high bit of 64 bit length set"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: high bit of 64 bit length set" ); } } while (0); |
1525 | return NS_ERROR_ILLEGAL_VALUE; |
1526 | } |
1527 | |
1528 | // copy this in case it is unaligned |
1529 | payloadLength64 = NetworkEndian::readInt64(mFramePtr + 2); |
1530 | |
1531 | if (payloadLength64 <= 0xffff) { |
1532 | // Section 5.2 says that the minimal number of bytes MUST |
1533 | // be used to encode the length in all cases |
1534 | LOG(("WebSocketChannel:: non-minimal-encoded payload length"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: non-minimal-encoded payload length" ); } } while (0); |
1535 | return NS_ERROR_ILLEGAL_VALUE; |
1536 | } |
1537 | } |
1538 | |
1539 | payload = mFramePtr + framingLength; |
1540 | avail -= framingLength; |
1541 | |
1542 | LOG(("WebSocketChannel::ProcessInput: payload %" PRId64 " avail %" PRIu32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %" "l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while (0) |
1543 | "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %" "l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while (0) |
1544 | payloadLength64, avail))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %" "l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while (0); |
1545 | |
1546 | CheckedInt<int64_t> payloadLengthChecked(payloadLength64); |
1547 | payloadLengthChecked += mFragmentAccumulator; |
1548 | if (!payloadLengthChecked.isValid() || |
1549 | payloadLengthChecked.value() > mMaxMessageSize) { |
1550 | return NS_ERROR_FILE_TOO_BIG; |
1551 | } |
1552 | |
1553 | uint32_t payloadLength = static_cast<uint32_t>(payloadLength64); |
1554 | |
1555 | if (avail < payloadLength) break; |
1556 | |
1557 | LOG(("WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n" , opcode); } } while (0) |
1558 | opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n" , opcode); } } while (0); |
1559 | |
1560 | if (!maskBit && mIsServerSide) { |
1561 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received " "from client\n"); } } while (0) |
1562 | ("WebSocketChannel::ProcessInput: unmasked frame received "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received " "from client\n"); } } while (0) |
1563 | "from client\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received " "from client\n"); } } while (0); |
1564 | return NS_ERROR_ILLEGAL_VALUE; |
1565 | } |
1566 | |
1567 | if (maskBit) { |
1568 | if (!mIsServerSide) { |
1569 | // The server should not be allowed to send masked frames to clients. |
1570 | // But we've been allowing it for some time, so this should be |
1571 | // deprecated with care. |
1572 | LOG(("WebSocketChannel:: Client RECEIVING masked frame."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Client RECEIVING masked frame." ); } } while (0); |
1573 | } |
1574 | |
1575 | mask = NetworkEndian::readUint32(payload - 4); |
1576 | } |
1577 | |
1578 | if (mask) { |
1579 | ApplyMask(mask, payload, payloadLength); |
1580 | } else if (mIsServerSide) { |
1581 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received" "from client\n"); } } while (0) |
1582 | ("WebSocketChannel::ProcessInput: masked frame with mask 0 received"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received" "from client\n"); } } while (0) |
1583 | "from client\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received" "from client\n"); } } while (0); |
1584 | return NS_ERROR_ILLEGAL_VALUE; |
1585 | } |
1586 | |
1587 | // Control codes are required to have the fin bit set |
1588 | if (!finBit && (opcode & kControlFrameMask)) { |
1589 | LOG(("WebSocketChannel:: fragmented control frame code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: fragmented control frame code %d\n" , opcode); } } while (0); |
1590 | return NS_ERROR_ILLEGAL_VALUE; |
1591 | } |
1592 | |
1593 | if (rsvBits) { |
1594 | // PMCE sets RSV1 bit in the first fragment when the non-control frame |
1595 | // is deflated |
1596 | MutexAutoLock lock(mCompressorMutex); |
1597 | if (mPMCECompressor && rsvBits == kRsv1Bit && mFragmentAccumulator == 0 && |
1598 | !(opcode & kControlFrameMask)) { |
1599 | mPMCECompressor->SetMessageDeflated(); |
1600 | LOG(("WebSocketChannel::ProcessInput: received deflated frame\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: received deflated frame\n" ); } } while (0); |
1601 | } else { |
1602 | LOG(("WebSocketChannel::ProcessInput: unexpected reserved bits %x\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unexpected reserved bits %x\n" , rsvBits); } } while (0) |
1603 | rsvBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unexpected reserved bits %x\n" , rsvBits); } } while (0); |
1604 | return NS_ERROR_ILLEGAL_VALUE; |
1605 | } |
1606 | } |
1607 | |
1608 | if (!finBit || opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1609 | // This is part of a fragment response |
1610 | |
1611 | // Only the first frame has a non zero op code: Make sure we don't see a |
1612 | // first frame while some old fragments are open |
1613 | if ((mFragmentAccumulator != 0) && |
1614 | (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION)) { |
1615 | LOG(("WebSocketChannel:: nested fragments\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: nested fragments\n" ); } } while (0); |
1616 | return NS_ERROR_ILLEGAL_VALUE; |
1617 | } |
1618 | |
1619 | LOG(("WebSocketChannel:: Accumulating Fragment %" PRIu32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Accumulating Fragment %" "u" "\n", payloadLength); } } while (0) |
1620 | payloadLength))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Accumulating Fragment %" "u" "\n", payloadLength); } } while (0); |
1621 | |
1622 | if (opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1623 | // Make sure this continuation fragment isn't the first fragment |
1624 | if (mFragmentOpcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1625 | LOG(("WebSocketHeandler:: continuation code in first fragment\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketHeandler:: continuation code in first fragment\n" ); } } while (0); |
1626 | return NS_ERROR_ILLEGAL_VALUE; |
1627 | } |
1628 | |
1629 | // For frag > 1 move the data body back on top of the headers |
1630 | // so we have contiguous stream of data |
1631 | MOZ_ASSERT(mFramePtr + framingLength == payload,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1632; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
1632 | "payload offset from frameptr wrong")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1632; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1633 | ::memmove(mFramePtr, payload, avail); |
1634 | payload = mFramePtr; |
1635 | if (mBuffered) mBuffered -= framingLength; |
1636 | } else { |
1637 | mFragmentOpcode = opcode; |
1638 | } |
1639 | |
1640 | if (finBit) { |
1641 | LOG(("WebSocketChannel:: Finalizing Fragment\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Finalizing Fragment\n" ); } } while (0); |
1642 | payload -= mFragmentAccumulator; |
1643 | payloadLength += mFragmentAccumulator; |
1644 | avail += mFragmentAccumulator; |
1645 | mFragmentAccumulator = 0; |
1646 | opcode = mFragmentOpcode; |
1647 | // reset to detect if next message illegally starts with continuation |
1648 | mFragmentOpcode = nsIWebSocketFrame::OPCODE_CONTINUATION; |
1649 | } else { |
1650 | opcode = nsIWebSocketFrame::OPCODE_CONTINUATION; |
1651 | mFragmentAccumulator += payloadLength; |
1652 | } |
1653 | } else if (mFragmentAccumulator != 0 && !(opcode & kControlFrameMask)) { |
1654 | // This frame is not part of a fragment sequence but we |
1655 | // have an open fragment.. it must be a control code or else |
1656 | // we have a problem |
1657 | LOG(("WebSocketChannel:: illegal fragment sequence\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: illegal fragment sequence\n" ); } } while (0); |
1658 | return NS_ERROR_ILLEGAL_VALUE; |
1659 | } |
1660 | |
1661 | if (mServerClosed) { |
1662 | LOG(("WebSocketChannel:: ignoring read frame code %d after close\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after close\n" , opcode); } } while (0) |
1663 | opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after close\n" , opcode); } } while (0); |
1664 | // nop |
1665 | } else if (mStopped) { |
1666 | LOG(("WebSocketChannel:: ignoring read frame code %d after completion\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after completion\n" , opcode); } } while (0) |
1667 | opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after completion\n" , opcode); } } while (0); |
1668 | } else if (opcode == nsIWebSocketFrame::OPCODE_TEXT) { |
1669 | if (mListenerMT) { |
1670 | nsCString utf8Data; |
1671 | { |
1672 | MutexAutoLock lock(mCompressorMutex); |
1673 | bool isDeflated = |
1674 | mPMCECompressor && mPMCECompressor->IsMessageDeflated(); |
1675 | LOG(("WebSocketChannel:: %stext frame received\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %stext frame received\n" , isDeflated ? "deflated " : ""); } } while (0) |
1676 | isDeflated ? "deflated " : ""))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %stext frame received\n" , isDeflated ? "deflated " : ""); } } while (0); |
1677 | |
1678 | if (isDeflated) { |
1679 | rv = mPMCECompressor->Inflate(payload, payloadLength, utf8Data); |
1680 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1681 | return rv; |
1682 | } |
1683 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0) |
1684 | ("WebSocketChannel:: message successfully inflated "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0) |
1685 | "[origLength=%d, newLength=%zd]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0) |
1686 | payloadLength, utf8Data.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0); |
1687 | } else { |
1688 | if (!utf8Data.Assign((const char*)payload, payloadLength, |
1689 | mozilla::fallible)) { |
1690 | return NS_ERROR_OUT_OF_MEMORY; |
1691 | } |
1692 | } |
1693 | } |
1694 | |
1695 | // Section 8.1 says to fail connection if invalid utf-8 in text message |
1696 | if (!IsUtf8(utf8Data)) { |
1697 | LOG(("WebSocketChannel:: text frame invalid utf-8\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: text frame invalid utf-8\n" ); } } while (0); |
1698 | return NS_ERROR_CANNOT_CONVERT_DATA; |
1699 | } |
1700 | |
1701 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
1702 | finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, utf8Data); |
1703 | |
1704 | if (frame) { |
1705 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1706 | } |
1707 | |
1708 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1709 | target->Dispatch(new CallOnMessageAvailable(this, utf8Data, -1), |
1710 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1711 | } else { |
1712 | return NS_ERROR_UNEXPECTED; |
1713 | } |
1714 | if (mConnectionLogService && !mPrivateBrowsing) { |
1715 | mConnectionLogService->NewMsgReceived(mHost, mSerial, count); |
1716 | LOG(("Added new msg received for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new msg received for %s" , mHost.get()); } } while (0); |
1717 | } |
1718 | } |
1719 | } else if (opcode & kControlFrameMask) { |
1720 | // control frames |
1721 | if (payloadLength > 125) { |
1722 | LOG(("WebSocketChannel:: bad control frame code %d length %d\n", opcode,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: bad control frame code %d length %d\n" , opcode, payloadLength); } } while (0) |
1723 | payloadLength))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: bad control frame code %d length %d\n" , opcode, payloadLength); } } while (0); |
1724 | return NS_ERROR_ILLEGAL_VALUE; |
1725 | } |
1726 | |
1727 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
1728 | finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, payload, |
1729 | payloadLength); |
1730 | |
1731 | if (opcode == nsIWebSocketFrame::OPCODE_CLOSE) { |
1732 | LOG(("WebSocketChannel:: close received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close received\n" ); } } while (0); |
1733 | mServerClosed = true; |
1734 | |
1735 | mServerCloseCode = CLOSE_NO_STATUS; |
1736 | if (payloadLength >= 2) { |
1737 | mServerCloseCode = NetworkEndian::readUint16(payload); |
1738 | LOG(("WebSocketChannel:: close recvd code %u\n", mServerCloseCode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close recvd code %u\n" , mServerCloseCode); } } while (0); |
1739 | uint16_t msglen = static_cast<uint16_t>(payloadLength - 2); |
1740 | if (msglen > 0) { |
1741 | mServerCloseReason.SetLength(msglen); |
1742 | memcpy(mServerCloseReason.BeginWriting(), (const char*)payload + 2, |
1743 | msglen); |
1744 | |
1745 | // section 8.1 says to replace received non utf-8 sequences |
1746 | // (which are non-conformant to send) with u+fffd, |
1747 | // but secteam feels that silently rewriting messages is |
1748 | // inappropriate - so we will fail the connection instead. |
1749 | if (!IsUtf8(mServerCloseReason)) { |
1750 | LOG(("WebSocketChannel:: close frame invalid utf-8\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close frame invalid utf-8\n" ); } } while (0); |
1751 | return NS_ERROR_CANNOT_CONVERT_DATA; |
1752 | } |
1753 | |
1754 | LOG(("WebSocketChannel:: close msg %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close msg %s\n" , mServerCloseReason.get()); } } while (0) |
1755 | mServerCloseReason.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close msg %s\n" , mServerCloseReason.get()); } } while (0); |
1756 | } |
1757 | } |
1758 | |
1759 | if (mCloseTimer) { |
1760 | mCloseTimer->Cancel(); |
1761 | mCloseTimer = nullptr; |
1762 | } |
1763 | |
1764 | if (frame) { |
1765 | // We send the frame immediately becuase we want to have it dispatched |
1766 | // before the CallOnServerClose. |
1767 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1768 | frame = nullptr; |
1769 | } |
1770 | |
1771 | if (mListenerMT) { |
1772 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1773 | target->Dispatch(new CallOnServerClose(this, mServerCloseCode, |
1774 | mServerCloseReason), |
1775 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1776 | } else { |
1777 | return NS_ERROR_UNEXPECTED; |
1778 | } |
1779 | } |
1780 | |
1781 | if (mClientClosed) ReleaseSession(); |
1782 | } else if (opcode == nsIWebSocketFrame::OPCODE_PING) { |
1783 | LOG(("WebSocketChannel:: ping received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ping received\n" ); } } while (0); |
1784 | GeneratePong(payload, payloadLength); |
1785 | } else if (opcode == nsIWebSocketFrame::OPCODE_PONG) { |
1786 | // opcode OPCODE_PONG: the mere act of receiving the packet is all we |
1787 | // need to do for the pong to trigger the activity timers |
1788 | LOG(("WebSocketChannel:: pong received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: pong received\n" ); } } while (0); |
1789 | } else { |
1790 | /* unknown control frame opcode */ |
1791 | LOG(("WebSocketChannel:: unknown control op code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: unknown control op code %d\n" , opcode); } } while (0); |
1792 | return NS_ERROR_ILLEGAL_VALUE; |
1793 | } |
1794 | |
1795 | if (mFragmentAccumulator) { |
1796 | // Remove the control frame from the stream so we have a contiguous |
1797 | // data buffer of reassembled fragments |
1798 | LOG(("WebSocketChannel:: Removing Control From Read buffer\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Removing Control From Read buffer\n" ); } } while (0); |
1799 | MOZ_ASSERT(mFramePtr + framingLength == payload,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1800; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
1800 | "payload offset from frameptr wrong")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1800; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1801 | ::memmove(mFramePtr, payload + payloadLength, avail - payloadLength); |
1802 | payload = mFramePtr; |
1803 | avail -= payloadLength; |
1804 | if (mBuffered) mBuffered -= framingLength + payloadLength; |
1805 | payloadLength = 0; |
1806 | } |
1807 | |
1808 | if (frame) { |
1809 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1810 | } |
1811 | } else if (opcode == nsIWebSocketFrame::OPCODE_BINARY) { |
1812 | if (mListenerMT) { |
1813 | nsCString binaryData; |
1814 | { |
1815 | MutexAutoLock lock(mCompressorMutex); |
1816 | bool isDeflated = |
1817 | mPMCECompressor && mPMCECompressor->IsMessageDeflated(); |
1818 | LOG(("WebSocketChannel:: %sbinary frame received\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %sbinary frame received\n" , isDeflated ? "deflated " : ""); } } while (0) |
1819 | isDeflated ? "deflated " : ""))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %sbinary frame received\n" , isDeflated ? "deflated " : ""); } } while (0); |
1820 | |
1821 | if (isDeflated) { |
1822 | rv = mPMCECompressor->Inflate(payload, payloadLength, binaryData); |
1823 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1824 | return rv; |
1825 | } |
1826 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0) |
1827 | ("WebSocketChannel:: message successfully inflated "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0) |
1828 | "[origLength=%d, newLength=%zd]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0) |
1829 | payloadLength, binaryData.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0); |
1830 | } else { |
1831 | if (!binaryData.Assign((const char*)payload, payloadLength, |
1832 | mozilla::fallible)) { |
1833 | return NS_ERROR_OUT_OF_MEMORY; |
1834 | } |
1835 | } |
1836 | } |
1837 | |
1838 | RefPtr<WebSocketFrame> frame = |
1839 | mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, |
1840 | opcode, maskBit, mask, binaryData); |
1841 | if (frame) { |
1842 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1843 | } |
1844 | |
1845 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1846 | target->Dispatch( |
1847 | new CallOnMessageAvailable(this, binaryData, binaryData.Length()), |
1848 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1849 | } else { |
1850 | return NS_ERROR_UNEXPECTED; |
1851 | } |
1852 | // To add the header to 'Networking Dashboard' log |
1853 | if (mConnectionLogService && !mPrivateBrowsing) { |
1854 | mConnectionLogService->NewMsgReceived(mHost, mSerial, count); |
1855 | LOG(("Added new received msg for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new received msg for %s" , mHost.get()); } } while (0); |
1856 | } |
1857 | } |
1858 | } else if (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1859 | /* unknown opcode */ |
1860 | LOG(("WebSocketChannel:: unknown op code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: unknown op code %d\n" , opcode); } } while (0); |
1861 | return NS_ERROR_ILLEGAL_VALUE; |
1862 | } |
1863 | |
1864 | mFramePtr = payload + payloadLength; |
1865 | avail -= payloadLength; |
1866 | totalAvail = avail; |
1867 | } |
1868 | |
1869 | // Adjust the stateful buffer. If we were operating off the stack and |
1870 | // now have a partial message then transition to the buffer, or if |
1871 | // we were working off the buffer but no longer have any active state |
1872 | // then transition to the stack |
1873 | if (!IsPersistentFramePtr()) { |
1874 | mBuffered = 0; |
1875 | |
1876 | if (mFragmentAccumulator) { |
1877 | LOG(("WebSocketChannel:: Setup Buffer due to fragment"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Setup Buffer due to fragment" ); } } while (0); |
1878 | |
1879 | if (!UpdateReadBuffer(mFramePtr - mFragmentAccumulator, |
1880 | totalAvail + mFragmentAccumulator, 0, nullptr)) { |
1881 | return NS_ERROR_FILE_TOO_BIG; |
1882 | } |
1883 | |
1884 | // UpdateReadBuffer will reset the frameptr to the beginning |
1885 | // of new saved state, so we need to skip past processed framgents |
1886 | mFramePtr += mFragmentAccumulator; |
1887 | } else if (totalAvail) { |
1888 | LOG(("WebSocketChannel:: Setup Buffer due to partial frame"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Setup Buffer due to partial frame" ); } } while (0); |
1889 | if (!UpdateReadBuffer(mFramePtr, totalAvail, 0, nullptr)) { |
1890 | return NS_ERROR_FILE_TOO_BIG; |
1891 | } |
1892 | } |
1893 | } else if (!mFragmentAccumulator && !totalAvail) { |
1894 | // If we were working off a saved buffer state and there is no partial |
1895 | // frame or fragment in process, then revert to stack behavior |
1896 | LOG(("WebSocketChannel:: Internal buffering not needed anymore"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Internal buffering not needed anymore" ); } } while (0); |
1897 | mBuffered = 0; |
1898 | |
1899 | // release memory if we've been processing a large message |
1900 | if (mBufferSize > kIncomingBufferStableSize) { |
1901 | mBufferSize = kIncomingBufferStableSize; |
1902 | free(mBuffer); |
1903 | mBuffer = (uint8_t*)moz_xmalloc(mBufferSize); |
1904 | } |
1905 | } |
1906 | return NS_OK; |
1907 | } |
1908 | |
1909 | /* static */ |
1910 | void WebSocketChannel::ApplyMask(uint32_t mask, uint8_t* data, uint64_t len) { |
1911 | if (!data || len == 0) return; |
1912 | |
1913 | // Optimally we want to apply the mask 32 bits at a time, |
1914 | // but the buffer might not be alligned. So we first deal with |
1915 | // 0 to 3 bytes of preamble individually |
1916 | |
1917 | while (len && (reinterpret_cast<uintptr_t>(data) & 3)) { |
1918 | *data ^= mask >> 24; |
1919 | mask = RotateLeft(mask, 8); |
1920 | data++; |
1921 | len--; |
1922 | } |
1923 | |
1924 | // perform mask on full words of data |
1925 | |
1926 | uint32_t* iData = (uint32_t*)data; |
1927 | uint32_t* end = iData + (len / 4); |
1928 | NetworkEndian::writeUint32(&mask, mask); |
1929 | for (; iData < end; iData++) *iData ^= mask; |
1930 | mask = NetworkEndian::readUint32(&mask); |
1931 | data = (uint8_t*)iData; |
1932 | len = len % 4; |
1933 | |
1934 | // There maybe up to 3 trailing bytes that need to be dealt with |
1935 | // individually |
1936 | |
1937 | while (len) { |
1938 | *data ^= mask >> 24; |
1939 | mask = RotateLeft(mask, 8); |
1940 | data++; |
1941 | len--; |
1942 | } |
1943 | } |
1944 | |
1945 | void WebSocketChannel::GeneratePing() { |
1946 | nsAutoCString buf; |
1947 | buf.AssignLiteral("PING"); |
1948 | EnqueueOutgoingMessage(mOutgoingPingMessages, |
1949 | new OutboundMessage(kMsgTypePing, buf)); |
1950 | } |
1951 | |
1952 | void WebSocketChannel::GeneratePong(uint8_t* payload, uint32_t len) { |
1953 | nsAutoCString buf; |
1954 | buf.SetLength(len); |
1955 | if (buf.Length() < len) { |
1956 | LOG(("WebSocketChannel::GeneratePong Allocation Failure\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GeneratePong Allocation Failure\n" ); } } while (0); |
1957 | return; |
1958 | } |
1959 | |
1960 | memcpy(buf.BeginWriting(), payload, len); |
1961 | EnqueueOutgoingMessage(mOutgoingPongMessages, |
1962 | new OutboundMessage(kMsgTypePong, buf)); |
1963 | } |
1964 | |
1965 | void WebSocketChannel::EnqueueOutgoingMessage(nsDeque<OutboundMessage>& aQueue, |
1966 | OutboundMessage* aMsg) { |
1967 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1967; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1968 | |
1969 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0) |
1970 | ("WebSocketChannel::EnqueueOutgoingMessage %p "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0) |
1971 | "queueing msg %p [type=%s len=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0) |
1972 | this, aMsg, msgNames[aMsg->GetMsgType()], aMsg->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0); |
1973 | |
1974 | aQueue.Push(aMsg); |
1975 | if (mSocketOut) { |
1976 | OnOutputStreamReady(mSocketOut); |
1977 | } else { |
1978 | DoEnqueueOutgoingMessage(); |
1979 | } |
1980 | } |
1981 | |
1982 | uint16_t WebSocketChannel::ResultToCloseCode(nsresult resultCode) { |
1983 | if (NS_SUCCEEDED(resultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(resultCode)), 1)) )) return CLOSE_NORMAL; |
1984 | |
1985 | switch (resultCode) { |
1986 | case NS_ERROR_FILE_TOO_BIG: |
1987 | case NS_ERROR_OUT_OF_MEMORY: |
1988 | return CLOSE_TOO_LARGE; |
1989 | case NS_ERROR_CANNOT_CONVERT_DATA: |
1990 | return CLOSE_INVALID_PAYLOAD; |
1991 | case NS_ERROR_UNEXPECTED: |
1992 | return CLOSE_INTERNAL_ERROR; |
1993 | default: |
1994 | return CLOSE_PROTOCOL_ERROR; |
1995 | } |
1996 | } |
1997 | |
1998 | void WebSocketChannel::PrimeNewOutgoingMessage() { |
1999 | LOG(("WebSocketChannel::PrimeNewOutgoingMessage() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage() %p\n" , this); } } while (0); |
2000 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2000); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 2000; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2001 | MOZ_ASSERT(!mCurrentOut, "Current message in progress")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCurrentOut)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCurrentOut))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCurrentOut" " (" "Current message in progress" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCurrentOut" ") (" "Current message in progress" ")"); do { *((volatile int *)__null) = 2001; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2002 | |
2003 | nsresult rv = NS_OK; |
2004 | |
2005 | mCurrentOut = mOutgoingPongMessages.PopFront(); |
2006 | if (mCurrentOut) { |
2007 | MOZ_ASSERT(mCurrentOut->GetMsgType() == kMsgTypePong, "Not pong message!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCurrentOut->GetMsgType() == kMsgTypePong)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mCurrentOut->GetMsgType() == kMsgTypePong))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePong" " (" "Not pong message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePong" ") (" "Not pong message!" ")"); do { *((volatile int*)__null ) = 2007; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2008 | } else { |
2009 | mCurrentOut = mOutgoingPingMessages.PopFront(); |
2010 | if (mCurrentOut) { |
2011 | MOZ_ASSERT(mCurrentOut->GetMsgType() == kMsgTypePing,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCurrentOut->GetMsgType() == kMsgTypePing)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mCurrentOut->GetMsgType() == kMsgTypePing))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePing" " (" "Not ping message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing" ") (" "Not ping message!" ")"); do { *((volatile int*)__null ) = 2012; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
2012 | "Not ping message!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCurrentOut->GetMsgType() == kMsgTypePing)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mCurrentOut->GetMsgType() == kMsgTypePing))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePing" " (" "Not ping message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing" ") (" "Not ping message!" ")"); do { *((volatile int*)__null ) = 2012; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2013 | } else { |
2014 | mCurrentOut = mOutgoingMessages.PopFront(); |
2015 | } |
2016 | } |
2017 | |
2018 | if (!mCurrentOut) return; |
2019 | |
2020 | auto cleanupAfterFailure = |
2021 | MakeScopeExit([&] { DeleteCurrentOutGoingMessage(); }); |
2022 | |
2023 | WsMsgType msgType = mCurrentOut->GetMsgType(); |
2024 | |
2025 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0) |
2026 | ("WebSocketChannel::PrimeNewOutgoingMessage "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0) |
2027 | "%p found queued msg %p [type=%s len=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0) |
2028 | this, mCurrentOut, msgNames[msgType], mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0); |
2029 | |
2030 | mCurrentOutSent = 0; |
2031 | mHdrOut = mOutHeader; |
2032 | |
2033 | uint8_t maskBit = mIsServerSide ? 0 : kMaskBit; |
2034 | uint8_t maskSize = mIsServerSide ? 0 : 4; |
2035 | |
2036 | uint8_t* payload = nullptr; |
2037 | |
2038 | if (msgType == kMsgTypeFin) { |
2039 | // This is a demand to create a close message |
2040 | if (mClientClosed) { |
2041 | DeleteCurrentOutGoingMessage(); |
2042 | PrimeNewOutgoingMessage(); |
2043 | cleanupAfterFailure.release(); |
2044 | return; |
2045 | } |
2046 | |
2047 | mClientClosed = true; |
2048 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_CLOSE; |
2049 | mOutHeader[1] = maskBit; |
2050 | |
2051 | // payload is offset 2 plus size of the mask |
2052 | payload = mOutHeader + 2 + maskSize; |
2053 | |
2054 | // The close reason code sits in the first 2 bytes of payload |
2055 | // If the channel user provided a code and reason during Close() |
2056 | // and there isn't an internal error, use that. |
2057 | if (NS_SUCCEEDED(mStopOnClose)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStopOnClose)), 1 )))) { |
2058 | MutexAutoLock lock(mMutex); |
2059 | if (mScriptCloseCode) { |
2060 | NetworkEndian::writeUint16(payload, mScriptCloseCode); |
2061 | mOutHeader[1] += 2; |
2062 | mHdrOutToSend = 4 + maskSize; |
2063 | if (!mScriptCloseReason.IsEmpty()) { |
2064 | MOZ_ASSERT(mScriptCloseReason.Length() <= 123,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mScriptCloseReason.Length() <= 123)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(mScriptCloseReason.Length() <= 123))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mScriptCloseReason.Length() <= 123" " (" "Close Reason Too Long" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123" ") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null ) = 2065; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
2065 | "Close Reason Too Long")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mScriptCloseReason.Length() <= 123)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(mScriptCloseReason.Length() <= 123))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mScriptCloseReason.Length() <= 123" " (" "Close Reason Too Long" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123" ") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null ) = 2065; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2066 | mOutHeader[1] += mScriptCloseReason.Length(); |
2067 | mHdrOutToSend += mScriptCloseReason.Length(); |
2068 | memcpy(payload + 2, mScriptCloseReason.BeginReading(), |
2069 | mScriptCloseReason.Length()); |
2070 | } |
2071 | } else { |
2072 | // No close code/reason, so payload length = 0. We must still send mask |
2073 | // even though it's not used. Keep payload offset so we write mask |
2074 | // below. |
2075 | mHdrOutToSend = 2 + maskSize; |
2076 | } |
2077 | } else { |
2078 | NetworkEndian::writeUint16(payload, ResultToCloseCode(mStopOnClose)); |
2079 | mOutHeader[1] += 2; |
2080 | mHdrOutToSend = 4 + maskSize; |
2081 | } |
2082 | |
2083 | if (mServerClosed) { |
2084 | /* bidi close complete */ |
2085 | mReleaseOnTransmit = 1; |
2086 | } else if (NS_FAILED(mStopOnClose)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStopOnClose)), 0) ))) { |
2087 | /* result of abort session - give up */ |
2088 | StopSession(mStopOnClose); |
2089 | } else { |
2090 | /* wait for reciprocal close from server */ |
2091 | rv = NS_NewTimerWithCallback(getter_AddRefs(mCloseTimer), this, |
2092 | mCloseTimeout, nsITimer::TYPE_ONE_SHOT); |
2093 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2094 | StopSession(rv); |
2095 | } |
2096 | } |
2097 | } else { |
2098 | switch (msgType) { |
2099 | case kMsgTypePong: |
2100 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PONG; |
2101 | break; |
2102 | case kMsgTypePing: |
2103 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PING; |
2104 | break; |
2105 | case kMsgTypeString: |
2106 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_TEXT; |
2107 | break; |
2108 | case kMsgTypeStream: |
2109 | // HACK ALERT: read in entire stream into string. |
2110 | // Will block socket transport thread if file is blocking. |
2111 | // TODO: bug 704447: don't block socket thread! |
2112 | rv = mCurrentOut->ConvertStreamToString(); |
2113 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2114 | AbortSession(NS_ERROR_FILE_TOO_BIG); |
2115 | return; |
2116 | } |
2117 | // Now we're a binary string |
2118 | msgType = kMsgTypeBinaryString; |
2119 | |
2120 | // no break: fall down into binary string case |
2121 | [[fallthrough]]; |
2122 | |
2123 | case kMsgTypeBinaryString: |
2124 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_BINARY; |
2125 | break; |
2126 | case kMsgTypeFin: |
2127 | MOZ_ASSERT(false, "unreachable")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "unreachable" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "unreachable" ")"); do { *((volatile int*)__null) = 2127; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); // avoid compiler warning |
2128 | break; |
2129 | } |
2130 | |
2131 | // deflate the payload if PMCE is negotiated |
2132 | MutexAutoLock lock(mCompressorMutex); |
2133 | if (mPMCECompressor && |
2134 | (msgType == kMsgTypeString || msgType == kMsgTypeBinaryString)) { |
2135 | if (mCurrentOut->DeflatePayload(mPMCECompressor.get())) { |
2136 | // The payload was deflated successfully, set RSV1 bit |
2137 | mOutHeader[0] |= kRsv1Bit; |
2138 | |
2139 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2140 | ("WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2141 | "deflated [origLength=%d, newLength=%d].\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2142 | this, mCurrentOut, mCurrentOut->OrigLength(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2143 | mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0); |
2144 | } |
2145 | } |
2146 | |
2147 | if (mCurrentOut->Length() < 126) { |
2148 | mOutHeader[1] = mCurrentOut->Length() | maskBit; |
2149 | mHdrOutToSend = 2 + maskSize; |
2150 | } else if (mCurrentOut->Length() <= 0xffff) { |
2151 | mOutHeader[1] = 126 | maskBit; |
2152 | NetworkEndian::writeUint16(mOutHeader + sizeof(uint16_t), |
2153 | mCurrentOut->Length()); |
2154 | mHdrOutToSend = 4 + maskSize; |
2155 | } else { |
2156 | mOutHeader[1] = 127 | maskBit; |
2157 | NetworkEndian::writeUint64(mOutHeader + 2, mCurrentOut->Length()); |
2158 | mHdrOutToSend = 10 + maskSize; |
2159 | } |
2160 | payload = mOutHeader + mHdrOutToSend; |
2161 | } |
2162 | |
2163 | MOZ_ASSERT(payload, "payload offset not found")do { static_assert( mozilla::detail::AssertionConditionType< decltype(payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("payload" " (" "payload offset not found" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2163); AnnotateMozCrashReason("MOZ_ASSERT" "(" "payload" ") (" "payload offset not found" ")"); do { *((volatile int*)__null ) = 2163; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2164 | |
2165 | uint32_t mask = 0; |
2166 | if (!mIsServerSide) { |
2167 | // Perform the sending mask. Never use a zero mask |
2168 | do { |
2169 | static_assert(4 == sizeof(mask), "Size of the mask should be equal to 4"); |
2170 | nsresult rv = mRandomGenerator->GenerateRandomBytesInto(mask); |
2171 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2172 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0) |
2173 | ("WebSocketChannel::PrimeNewOutgoingMessage(): "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0) |
2174 | "GenerateRandomBytes failure %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0) |
2175 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0); |
2176 | AbortSession(rv); |
2177 | return; |
2178 | } |
2179 | } while (!mask); |
2180 | NetworkEndian::writeUint32(payload - sizeof(uint32_t), mask); |
2181 | } |
2182 | |
2183 | LOG(("WebSocketChannel::PrimeNewOutgoingMessage() using mask %08x\n", mask))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage() using mask %08x\n" , mask); } } while (0); |
2184 | |
2185 | // We don't mask the framing, but occasionally we stick a little payload |
2186 | // data in the buffer used for the framing. Close frames are the current |
2187 | // example. This data needs to be masked, but it is never more than a |
2188 | // handful of bytes and might rotate the mask, so we can just do it locally. |
2189 | // For real data frames we ship the bulk of the payload off to ApplyMask() |
2190 | |
2191 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
2192 | mOutHeader[0] & WebSocketChannel::kFinalFragBit, |
2193 | mOutHeader[0] & WebSocketChannel::kRsv1Bit, |
2194 | mOutHeader[0] & WebSocketChannel::kRsv2Bit, |
2195 | mOutHeader[0] & WebSocketChannel::kRsv3Bit, |
2196 | mOutHeader[0] & WebSocketChannel::kOpcodeBitsMask, |
2197 | mOutHeader[1] & WebSocketChannel::kMaskBit, mask, payload, |
2198 | mHdrOutToSend - (payload - mOutHeader), mCurrentOut->BeginOrigReading(), |
2199 | mCurrentOut->OrigLength()); |
2200 | |
2201 | if (frame) { |
2202 | mService->FrameSent(mSerial, mInnerWindowID, frame.forget()); |
2203 | } |
2204 | |
2205 | if (mask) { |
2206 | while (payload < (mOutHeader + mHdrOutToSend)) { |
2207 | *payload ^= mask >> 24; |
2208 | mask = RotateLeft(mask, 8); |
2209 | payload++; |
2210 | } |
2211 | |
2212 | // Mask the real message payloads |
2213 | ApplyMask(mask, mCurrentOut->BeginWriting(), mCurrentOut->Length()); |
2214 | } |
2215 | |
2216 | int32_t len = mCurrentOut->Length(); |
2217 | |
2218 | // for small frames, copy it all together for a contiguous write |
2219 | if (len && len <= kCopyBreak) { |
2220 | memcpy(mOutHeader + mHdrOutToSend, mCurrentOut->BeginWriting(), len); |
2221 | mHdrOutToSend += len; |
2222 | mCurrentOutSent = len; |
2223 | } |
2224 | |
2225 | // Transmitting begins - mHdrOutToSend bytes from mOutHeader and |
2226 | // mCurrentOut->Length() bytes from mCurrentOut. The latter may be |
2227 | // coaleseced into the former for small messages or as the result of the |
2228 | // compression process. |
2229 | |
2230 | cleanupAfterFailure.release(); |
2231 | } |
2232 | |
2233 | void WebSocketChannel::DeleteCurrentOutGoingMessage() { |
2234 | delete mCurrentOut; |
2235 | mCurrentOut = nullptr; |
2236 | mCurrentOutSent = 0; |
2237 | } |
2238 | |
2239 | void WebSocketChannel::EnsureHdrOut(uint32_t size) { |
2240 | LOG(("WebSocketChannel::EnsureHdrOut() %p [%d]\n", this, size))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnsureHdrOut() %p [%d]\n" , this, size); } } while (0); |
2241 | |
2242 | if (mDynamicOutputSize < size) { |
2243 | mDynamicOutputSize = size; |
2244 | mDynamicOutput = (uint8_t*)moz_xrealloc(mDynamicOutput, mDynamicOutputSize); |
2245 | } |
2246 | |
2247 | mHdrOut = mDynamicOutput; |
2248 | } |
2249 | |
2250 | namespace { |
2251 | |
2252 | class RemoveObserverRunnable : public Runnable { |
2253 | RefPtr<WebSocketChannel> mChannel; |
2254 | |
2255 | public: |
2256 | explicit RemoveObserverRunnable(WebSocketChannel* aChannel) |
2257 | : Runnable("net::RemoveObserverRunnable"), mChannel(aChannel) {} |
2258 | |
2259 | NS_IMETHODvirtual nsresult Run() override { |
2260 | nsCOMPtr<nsIObserverService> observerService = |
2261 | mozilla::services::GetObserverService(); |
2262 | if (!observerService) { |
2263 | NS_WARNING("failed to get observer service")NS_DebugBreak(NS_DEBUG_WARNING, "failed to get observer service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2263); |
2264 | return NS_OK; |
2265 | } |
2266 | |
2267 | observerService->RemoveObserver(mChannel, NS_NETWORK_LINK_TOPIC"network:link-status-changed"); |
2268 | return NS_OK; |
2269 | } |
2270 | }; |
2271 | |
2272 | } // namespace |
2273 | |
2274 | void WebSocketChannel::CleanupConnection() { |
2275 | // normally this should be called on socket thread, but it may be called |
2276 | // on MainThread |
2277 | |
2278 | LOG(("WebSocketChannel::CleanupConnection() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CleanupConnection() %p" , this); } } while (0); |
2279 | // This needs to run on the IOThread so we don't need to lock a bunch of these |
2280 | if (!mIOThread->IsOnCurrentThread()) { |
2281 | mIOThread->Dispatch( |
2282 | NewRunnableMethod("net::WebSocketChannel::CleanupConnection", this, |
2283 | &WebSocketChannel::CleanupConnection), |
2284 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2285 | return; |
2286 | } |
2287 | |
2288 | if (mLingeringCloseTimer) { |
2289 | mLingeringCloseTimer->Cancel(); |
2290 | mLingeringCloseTimer = nullptr; |
2291 | } |
2292 | |
2293 | if (mSocketIn) { |
2294 | if (mDataStarted) { |
2295 | mSocketIn->AsyncWait(nullptr, 0, 0, nullptr); |
2296 | } |
2297 | mSocketIn = nullptr; |
2298 | } |
2299 | |
2300 | if (mSocketOut) { |
2301 | mSocketOut->AsyncWait(nullptr, 0, 0, nullptr); |
2302 | mSocketOut = nullptr; |
2303 | } |
2304 | |
2305 | if (mTransport) { |
2306 | mTransport->SetSecurityCallbacks(nullptr); |
2307 | mTransport->SetEventSink(nullptr, nullptr); |
2308 | mTransport->Close(NS_BASE_STREAM_CLOSED); |
2309 | mTransport = nullptr; |
2310 | } |
2311 | |
2312 | if (mConnection) { |
2313 | mConnection->Close(); |
2314 | mConnection = nullptr; |
2315 | } |
2316 | |
2317 | if (mConnectionLogService && !mPrivateBrowsing) { |
2318 | mConnectionLogService->RemoveHost(mHost, mSerial); |
2319 | } |
2320 | |
2321 | // The observer has to be removed on the main-thread. |
2322 | NS_DispatchToMainThread(new RemoveObserverRunnable(this)); |
2323 | |
2324 | DecrementSessionCount(); |
2325 | } |
2326 | |
2327 | void WebSocketChannel::StopSession(nsresult reason) { |
2328 | LOG(("WebSocketChannel::StopSession() %p [%" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0) |
2329 | static_cast<uint32_t>(reason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0); |
2330 | |
2331 | { |
2332 | MutexAutoLock lock(mMutex); |
2333 | if (mStopped) { |
2334 | return; |
2335 | } |
2336 | mStopped = true; |
2337 | } |
2338 | |
2339 | DoStopSession(reason); |
2340 | } |
2341 | |
2342 | void WebSocketChannel::DoStopSession(nsresult reason) { |
2343 | LOG(("WebSocketChannel::DoStopSession() %p [%" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0) |
2344 | static_cast<uint32_t>(reason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0); |
2345 | |
2346 | // normally this should be called on socket thread, but it is ok to call it |
2347 | // from OnStartRequest before the socket thread machine has gotten underway. |
2348 | // If mDataStarted is false, this is called on MainThread for Close(). |
2349 | // Otherwise it should be called on the IO thread |
2350 | |
2351 | MOZ_ASSERT(mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2351); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")" ); do { *((volatile int*)__null) = 2351; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2352 | MOZ_ASSERT(mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread() || mTCPClosed || ! mDataStarted)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted" ")"); do { *((volatile int*)__null) = 2352; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2353 | |
2354 | if (!mOpenedHttpChannel) { |
2355 | // The HTTP channel information will never be used in this case |
2356 | NS_ReleaseOnMainThread("WebSocketChannel::mChannel", mChannel.forget()); |
2357 | NS_ReleaseOnMainThread("WebSocketChannel::mHttpChannel", |
2358 | mHttpChannel.forget()); |
2359 | NS_ReleaseOnMainThread("WebSocketChannel::mLoadGroup", mLoadGroup.forget()); |
2360 | NS_ReleaseOnMainThread("WebSocketChannel::mCallbacks", mCallbacks.forget()); |
2361 | } |
2362 | |
2363 | if (mCloseTimer) { |
2364 | mCloseTimer->Cancel(); |
2365 | mCloseTimer = nullptr; |
2366 | } |
2367 | |
2368 | // mOpenTimer must be null if mDataStarted is true and we're not on MainThread |
2369 | if (mOpenTimer) { |
2370 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2370; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2371 | mOpenTimer->Cancel(); |
2372 | mOpenTimer = nullptr; |
2373 | } |
2374 | |
2375 | { |
2376 | MutexAutoLock lock(mMutex); |
2377 | if (mReconnectDelayTimer) { |
2378 | mReconnectDelayTimer->Cancel(); |
2379 | NS_ReleaseOnMainThread("WebSocketChannel::mMutex", |
2380 | mReconnectDelayTimer.forget()); |
2381 | } |
2382 | } |
2383 | |
2384 | if (mPingTimer) { |
2385 | mPingTimer->Cancel(); |
2386 | mPingTimer = nullptr; |
2387 | } |
2388 | |
2389 | if (!mTCPClosed && mDataStarted) { |
2390 | if (mSocketIn) { |
2391 | // Drain, within reason, this socket. if we leave any data |
2392 | // unconsumed (including the tcp fin) a RST will be generated |
2393 | // The right thing to do here is shutdown(SHUT_WR) and then wait |
2394 | // a little while to see if any data comes in.. but there is no |
2395 | // reason to delay things for that when the websocket handshake |
2396 | // is supposed to guarantee a quiet connection except for that fin. |
2397 | |
2398 | char buffer[512]; |
2399 | uint32_t count = 0; |
2400 | uint32_t total = 0; |
2401 | nsresult rv; |
2402 | do { |
2403 | total += count; |
2404 | rv = mSocketIn->Read(buffer, 512, &count); |
2405 | if (rv != NS_BASE_STREAM_WOULD_BLOCK && (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || count == 0)) { |
2406 | mTCPClosed = true; |
2407 | } |
2408 | } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && count > 0 && total < 32000); |
2409 | } else if (mConnection) { |
2410 | mConnection->DrainSocketData(); |
2411 | } |
2412 | } |
2413 | |
2414 | int32_t sessionCount = kLingeringCloseThreshold; |
2415 | nsWSAdmissionManager::GetSessionCount(sessionCount); |
2416 | |
2417 | if (!mTCPClosed && (mTransport || mConnection) && |
2418 | sessionCount < kLingeringCloseThreshold) { |
2419 | // 7.1.1 says that the client SHOULD wait for the server to close the TCP |
2420 | // connection. This is so we can reuse port numbers before 2 MSL expires, |
2421 | // which is not really as much of a concern for us as the amount of state |
2422 | // that might be accrued by keeping this channel object around waiting for |
2423 | // the server. We handle the SHOULD by waiting a short time in the common |
2424 | // case, but not waiting in the case of high concurrency. |
2425 | // |
2426 | // Normally this will be taken care of in AbortSession() after mTCPClosed |
2427 | // is set when the server close arrives without waiting for the timeout to |
2428 | // expire. |
2429 | |
2430 | LOG(("WebSocketChannel::DoStopSession: Wait for Server TCP close"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession: Wait for Server TCP close" ); } } while (0); |
2431 | |
2432 | nsresult rv; |
2433 | rv = NS_NewTimerWithCallback(getter_AddRefs(mLingeringCloseTimer), this, |
2434 | kLingeringCloseTimeout, |
2435 | nsITimer::TYPE_ONE_SHOT); |
2436 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CleanupConnection(); |
2437 | } else { |
2438 | CleanupConnection(); |
2439 | } |
2440 | |
2441 | { |
2442 | MutexAutoLock lock(mMutex); |
2443 | if (mCancelable) { |
2444 | mCancelable->Cancel(NS_ERROR_UNEXPECTED); |
2445 | mCancelable = nullptr; |
2446 | } |
2447 | } |
2448 | |
2449 | { |
2450 | MutexAutoLock lock(mCompressorMutex); |
2451 | mPMCECompressor = nullptr; |
2452 | } |
2453 | if (!mCalledOnStop) { |
2454 | mCalledOnStop = true; |
2455 | |
2456 | nsWSAdmissionManager::OnStopSession(this, reason); |
2457 | |
2458 | RefPtr<CallOnStop> runnable = new CallOnStop(this, reason); |
2459 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
2460 | target->Dispatch(runnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2461 | } |
2462 | } |
2463 | } |
2464 | |
2465 | // Called from MainThread, and called from IOThread in |
2466 | // PrimeNewOutgoingMessage |
2467 | void WebSocketChannel::AbortSession(nsresult reason) { |
2468 | LOG(("WebSocketChannel::AbortSession() %p [reason %" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %" "x" "] stopped = %d\n", this, static_cast<uint32_t>(reason ), !!mStopped); } } while (0) |
2469 | "] stopped = %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %" "x" "] stopped = %d\n", this, static_cast<uint32_t>(reason ), !!mStopped); } } while (0) |
2470 | this, static_cast<uint32_t>(reason), !!mStopped))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %" "x" "] stopped = %d\n", this, static_cast<uint32_t>(reason ), !!mStopped); } } while (0); |
2471 | |
2472 | MOZ_ASSERT(NS_FAILED(reason), "reason must be a failure!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))" " (" "reason must be a failure!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))" ") (" "reason must be a failure!" ")"); do { *((volatile int *)__null) = 2472; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2473 | |
2474 | // normally this should be called on socket thread, but it is ok to call it |
2475 | // from the main thread before StartWebsocketData() has completed |
2476 | MOZ_ASSERT(mIOThread->IsOnCurrentThread() || !mDataStarted)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread() || !mDataStarted)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mIOThread->IsOnCurrentThread() || !mDataStarted)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mIOThread->IsOnCurrentThread() || !mDataStarted" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || !mDataStarted" ")"); do { *((volatile int*)__null) = 2476; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2477 | |
2478 | // When we are failing we need to close the TCP connection immediately |
2479 | // as per 7.1.1 |
2480 | mTCPClosed = true; |
2481 | |
2482 | if (mLingeringCloseTimer) { |
2483 | MOZ_ASSERT(mStopped, "Lingering without Stop")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped" " (" "Lingering without Stop" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") (" "Lingering without Stop" ")"); do { *((volatile int*)__null) = 2483; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2484 | LOG(("WebSocketChannel:: Cleanup connection based on TCP Close"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Cleanup connection based on TCP Close" ); } } while (0); |
2485 | CleanupConnection(); |
2486 | return; |
2487 | } |
2488 | |
2489 | { |
2490 | MutexAutoLock lock(mMutex); |
2491 | if (mStopped) { |
2492 | return; |
2493 | } |
2494 | |
2495 | if ((mTransport || mConnection) && reason != NS_BASE_STREAM_CLOSED && |
2496 | !mRequestedClose && !mClientClosed && !mServerClosed && mDataStarted) { |
2497 | mRequestedClose = true; |
2498 | mStopOnClose = reason; |
2499 | mIOThread->Dispatch( |
2500 | new OutboundEnqueuer(this, |
2501 | new OutboundMessage(kMsgTypeFin, VoidCString())), |
2502 | nsIEventTarget::DISPATCH_NORMAL); |
2503 | return; |
2504 | } |
2505 | |
2506 | mStopped = true; |
2507 | } |
2508 | |
2509 | DoStopSession(reason); |
2510 | } |
2511 | |
2512 | // ReleaseSession is called on orderly shutdown |
2513 | void WebSocketChannel::ReleaseSession() { |
2514 | LOG(("WebSocketChannel::ReleaseSession() %p stopped = %d\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReleaseSession() %p stopped = %d\n" , this, !!mStopped); } } while (0) |
2515 | !!mStopped))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReleaseSession() %p stopped = %d\n" , this, !!mStopped); } } while (0); |
2516 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 2516; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2517 | |
2518 | StopSession(NS_OK); |
2519 | } |
2520 | |
2521 | void WebSocketChannel::IncrementSessionCount() { |
2522 | if (!mIncrementedSessionCount) { |
2523 | nsWSAdmissionManager::IncrementSessionCount(); |
2524 | mIncrementedSessionCount = true; |
2525 | } |
2526 | } |
2527 | |
2528 | void WebSocketChannel::DecrementSessionCount() { |
2529 | // Make sure we decrement session count only once, and only if we incremented |
2530 | // it. This code is thread-safe: sWebSocketAdmissions->DecrementSessionCount |
2531 | // is atomic, and mIncrementedSessionCount/mDecrementedSessionCount are set at |
2532 | // times when they'll never be a race condition for checking/setting them. |
2533 | if (mIncrementedSessionCount && !mDecrementedSessionCount) { |
2534 | nsWSAdmissionManager::DecrementSessionCount(); |
2535 | mDecrementedSessionCount = true; |
2536 | } |
2537 | } |
2538 | |
2539 | namespace { |
2540 | enum ExtensionParseMode { eParseServerSide, eParseClientSide }; |
2541 | } |
2542 | |
2543 | static nsresult ParseWebSocketExtension(const nsACString& aExtension, |
2544 | ExtensionParseMode aMode, |
2545 | bool& aClientNoContextTakeover, |
2546 | bool& aServerNoContextTakeover, |
2547 | int32_t& aClientMaxWindowBits, |
2548 | int32_t& aServerMaxWindowBits) { |
2549 | nsCCharSeparatedTokenizer tokens(aExtension, ';'); |
2550 | |
2551 | if (!tokens.hasMoreTokens() || |
2552 | !tokens.nextToken().EqualsLiteral("permessage-deflate")) { |
2553 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0) |
2554 | ("WebSocketChannel::ParseWebSocketExtension: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0) |
2555 | "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0) |
2556 | PromiseFlatCString(aExtension).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0); |
2557 | return NS_ERROR_ILLEGAL_VALUE; |
2558 | } |
2559 | |
2560 | aClientNoContextTakeover = aServerNoContextTakeover = false; |
2561 | aClientMaxWindowBits = aServerMaxWindowBits = -1; |
2562 | |
2563 | while (tokens.hasMoreTokens()) { |
2564 | auto token = tokens.nextToken(); |
2565 | |
2566 | int32_t nameEnd, valueStart; |
2567 | int32_t delimPos = token.FindChar('='); |
2568 | if (delimPos == kNotFound) { |
2569 | nameEnd = token.Length(); |
2570 | valueStart = token.Length(); |
2571 | } else { |
2572 | nameEnd = delimPos; |
2573 | valueStart = delimPos + 1; |
2574 | } |
2575 | |
2576 | auto paramName = Substring(token, 0, nameEnd); |
2577 | auto paramValue = Substring(token, valueStart); |
2578 | |
2579 | if (paramName.EqualsLiteral("client_no_context_takeover")) { |
2580 | if (!paramValue.IsEmpty()) { |
2581 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2582 | ("WebSocketChannel::ParseWebSocketExtension: parameter "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2583 | "client_no_context_takeover must not have value, found %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2584 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0); |
2585 | return NS_ERROR_ILLEGAL_VALUE; |
2586 | } |
2587 | if (aClientNoContextTakeover) { |
2588 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_no_context_takeover\n"); } } while (0) |
2589 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_no_context_takeover\n"); } } while (0) |
2590 | "parameters client_no_context_takeover\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_no_context_takeover\n"); } } while (0); |
2591 | return NS_ERROR_ILLEGAL_VALUE; |
2592 | } |
2593 | aClientNoContextTakeover = true; |
2594 | } else if (paramName.EqualsLiteral("server_no_context_takeover")) { |
2595 | if (!paramValue.IsEmpty()) { |
2596 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2597 | ("WebSocketChannel::ParseWebSocketExtension: parameter "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2598 | "server_no_context_takeover must not have value, found %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2599 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0); |
2600 | return NS_ERROR_ILLEGAL_VALUE; |
2601 | } |
2602 | if (aServerNoContextTakeover) { |
2603 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_no_context_takeover\n"); } } while (0) |
2604 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_no_context_takeover\n"); } } while (0) |
2605 | "parameters server_no_context_takeover\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_no_context_takeover\n"); } } while (0); |
2606 | return NS_ERROR_ILLEGAL_VALUE; |
2607 | } |
2608 | aServerNoContextTakeover = true; |
2609 | } else if (paramName.EqualsLiteral("client_max_window_bits")) { |
2610 | if (aClientMaxWindowBits != -1) { |
2611 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_max_window_bits\n"); } } while (0) |
2612 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_max_window_bits\n"); } } while (0) |
2613 | "parameters client_max_window_bits\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_max_window_bits\n"); } } while (0); |
2614 | return NS_ERROR_ILLEGAL_VALUE; |
2615 | } |
2616 | |
2617 | if (aMode == eParseServerSide && paramValue.IsEmpty()) { |
2618 | // Use -2 to indicate that "client_max_window_bits" has been parsed, |
2619 | // but had no value. |
2620 | aClientMaxWindowBits = -2; |
2621 | } else { |
2622 | nsresult errcode; |
2623 | aClientMaxWindowBits = |
2624 | PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode); |
2625 | if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aClientMaxWindowBits < 8 || |
2626 | aClientMaxWindowBits > 15) { |
2627 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2628 | ("WebSocketChannel::ParseWebSocketExtension: found invalid "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2629 | "parameter client_max_window_bits %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2630 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0); |
2631 | return NS_ERROR_ILLEGAL_VALUE; |
2632 | } |
2633 | } |
2634 | } else if (paramName.EqualsLiteral("server_max_window_bits")) { |
2635 | if (aServerMaxWindowBits != -1) { |
2636 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_max_window_bits\n"); } } while (0) |
2637 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_max_window_bits\n"); } } while (0) |
2638 | "parameters server_max_window_bits\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_max_window_bits\n"); } } while (0); |
2639 | return NS_ERROR_ILLEGAL_VALUE; |
2640 | } |
2641 | |
2642 | nsresult errcode; |
2643 | aServerMaxWindowBits = PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode); |
2644 | if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aServerMaxWindowBits < 8 || |
2645 | aServerMaxWindowBits > 15) { |
2646 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2647 | ("WebSocketChannel::ParseWebSocketExtension: found invalid "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2648 | "parameter server_max_window_bits %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2649 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0); |
2650 | return NS_ERROR_ILLEGAL_VALUE; |
2651 | } |
2652 | } else { |
2653 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0) |
2654 | ("WebSocketChannel::ParseWebSocketExtension: found unknown "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0) |
2655 | "parameter %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0) |
2656 | PromiseFlatCString(paramName).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0); |
2657 | return NS_ERROR_ILLEGAL_VALUE; |
2658 | } |
2659 | } |
2660 | |
2661 | if (aClientMaxWindowBits == -2) { |
2662 | aClientMaxWindowBits = -1; |
2663 | } |
2664 | |
2665 | return NS_OK; |
2666 | } |
2667 | |
2668 | nsresult WebSocketChannel::HandleExtensions() { |
2669 | LOG(("WebSocketChannel::HandleExtensions() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions() %p\n" , this); } } while (0); |
2670 | |
2671 | nsresult rv; |
2672 | nsAutoCString extensions; |
2673 | |
2674 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2674; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2675 | |
2676 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Extensions"_ns, |
Value stored to 'rv' is never read | |
2677 | extensions); |
2678 | extensions.CompressWhitespace(); |
2679 | if (extensions.IsEmpty()) { |
2680 | return NS_OK; |
2681 | } |
2682 | |
2683 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0) |
2684 | ("WebSocketChannel::HandleExtensions: received "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0) |
2685 | "Sec-WebSocket-Extensions header: %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0) |
2686 | extensions.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0); |
2687 | |
2688 | bool clientNoContextTakeover; |
2689 | bool serverNoContextTakeover; |
2690 | int32_t clientMaxWindowBits; |
2691 | int32_t serverMaxWindowBits; |
2692 | |
2693 | rv = ParseWebSocketExtension(extensions, eParseClientSide, |
2694 | clientNoContextTakeover, serverNoContextTakeover, |
2695 | clientMaxWindowBits, serverMaxWindowBits); |
2696 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2697 | AbortSession(rv); |
2698 | return rv; |
2699 | } |
2700 | |
2701 | if (clientMaxWindowBits == -1) { |
2702 | clientMaxWindowBits = 15; |
2703 | } |
2704 | if (serverMaxWindowBits == -1) { |
2705 | serverMaxWindowBits = 15; |
2706 | } |
2707 | |
2708 | MutexAutoLock lock(mCompressorMutex); |
2709 | mPMCECompressor = MakeUnique<PMCECompression>( |
2710 | clientNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits); |
2711 | if (mPMCECompressor->Active()) { |
2712 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2713 | ("WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2714 | "context takeover, clientMaxWindowBits=%d, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2715 | "serverMaxWindowBits=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2716 | clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2717 | serverMaxWindowBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0); |
2718 | |
2719 | mNegotiatedExtensions = "permessage-deflate"; |
2720 | } else { |
2721 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE " "compression object\n"); } } while (0) |
2722 | ("WebSocketChannel::HandleExtensions: Cannot init PMCE "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE " "compression object\n"); } } while (0) |
2723 | "compression object\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE " "compression object\n"); } } while (0); |
2724 | mPMCECompressor = nullptr; |
2725 | AbortSession(NS_ERROR_UNEXPECTED); |
2726 | return NS_ERROR_UNEXPECTED; |
2727 | } |
2728 | |
2729 | return NS_OK; |
2730 | } |
2731 | |
2732 | void ProcessServerWebSocketExtensions(const nsACString& aExtensions, |
2733 | nsACString& aNegotiatedExtensions) { |
2734 | aNegotiatedExtensions.Truncate(); |
2735 | |
2736 | for (const auto& ext : |
2737 | nsCCharSeparatedTokenizer(aExtensions, ',').ToRange()) { |
2738 | bool clientNoContextTakeover; |
2739 | bool serverNoContextTakeover; |
2740 | int32_t clientMaxWindowBits; |
2741 | int32_t serverMaxWindowBits; |
2742 | |
2743 | nsresult rv = ParseWebSocketExtension( |
2744 | ext, eParseServerSide, clientNoContextTakeover, serverNoContextTakeover, |
2745 | clientMaxWindowBits, serverMaxWindowBits); |
2746 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2747 | // Ignore extensions that we can't parse |
2748 | continue; |
2749 | } |
2750 | |
2751 | aNegotiatedExtensions.AssignLiteral("permessage-deflate"); |
2752 | if (clientNoContextTakeover) { |
2753 | aNegotiatedExtensions.AppendLiteral(";client_no_context_takeover"); |
2754 | } |
2755 | if (serverNoContextTakeover) { |
2756 | aNegotiatedExtensions.AppendLiteral(";server_no_context_takeover"); |
2757 | } |
2758 | if (clientMaxWindowBits != -1) { |
2759 | aNegotiatedExtensions.AppendLiteral(";client_max_window_bits="); |
2760 | aNegotiatedExtensions.AppendInt(clientMaxWindowBits); |
2761 | } |
2762 | if (serverMaxWindowBits != -1) { |
2763 | aNegotiatedExtensions.AppendLiteral(";server_max_window_bits="); |
2764 | aNegotiatedExtensions.AppendInt(serverMaxWindowBits); |
2765 | } |
2766 | |
2767 | return; |
2768 | } |
2769 | } |
2770 | |
2771 | nsresult CalculateWebSocketHashedSecret(const nsACString& aKey, |
2772 | nsACString& aHash) { |
2773 | nsresult rv; |
2774 | nsCString key = aKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_ns; |
2775 | nsCOMPtr<nsICryptoHash> hasher = |
2776 | do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv); |
2777 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2777); return rv; } } while (false); |
2778 | rv = hasher->Init(nsICryptoHash::SHA1); |
2779 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2779); return rv; } } while (false); |
2780 | rv = hasher->Update((const uint8_t*)key.BeginWriting(), key.Length()); |
2781 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2781); return rv; } } while (false); |
2782 | return hasher->Finish(true, aHash); |
2783 | } |
2784 | |
2785 | nsresult WebSocketChannel::SetupRequest() { |
2786 | LOG(("WebSocketChannel::SetupRequest() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest() %p\n" , this); } } while (0); |
2787 | |
2788 | nsresult rv; |
2789 | |
2790 | if (mLoadGroup) { |
2791 | rv = mHttpChannel->SetLoadGroup(mLoadGroup); |
2792 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2792); return rv; } } while (false); |
2793 | } |
2794 | |
2795 | rv = mHttpChannel->SetLoadFlags( |
2796 | nsIRequest::LOAD_BACKGROUND | nsIRequest::INHIBIT_CACHING | |
2797 | nsIRequest::LOAD_BYPASS_CACHE | nsIChannel::LOAD_BYPASS_SERVICE_WORKER); |
2798 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2798); return rv; } } while (false); |
2799 | |
2800 | // we never let websockets be blocked by head CSS/JS loads to avoid |
2801 | // potential deadlock where server generation of CSS/JS requires |
2802 | // an XHR signal. |
2803 | nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel)); |
2804 | if (cos) { |
2805 | cos->AddClassFlags(nsIClassOfService::Unblocked); |
2806 | } |
2807 | |
2808 | // draft-ietf-hybi-thewebsocketprotocol-07 illustrates Upgrade: websocket |
2809 | // in lower case, so go with that. It is technically case insensitive. |
2810 | rv = mChannel->HTTPUpgrade("websocket"_ns, this); |
2811 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2811); return rv; } } while (false); |
2812 | |
2813 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Version"_ns, |
2814 | nsLiteralCString(SEC_WEBSOCKET_VERSION"13"), |
2815 | false); |
2816 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2816; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2817 | |
2818 | if (!mOrigin.IsEmpty()) { |
2819 | rv = mHttpChannel->SetRequestHeader("Origin"_ns, mOrigin, false); |
2820 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2820; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2821 | } |
2822 | |
2823 | if (!mProtocol.IsEmpty()) { |
2824 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Protocol"_ns, mProtocol, |
2825 | true); |
2826 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2826; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2827 | } |
2828 | |
2829 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Extensions"_ns, |
2830 | "permessage-deflate"_ns, false); |
2831 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2831; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2832 | |
2833 | uint8_t* secKey; |
2834 | nsAutoCString secKeyString; |
2835 | |
2836 | rv = mRandomGenerator->GenerateRandomBytes(16, &secKey); |
2837 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2837); return rv; } } while (false); |
2838 | rv = Base64Encode(reinterpret_cast<const char*>(secKey), 16, secKeyString); |
2839 | free(secKey); |
2840 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2841 | return rv; |
2842 | } |
2843 | |
2844 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Key"_ns, secKeyString, |
2845 | false); |
2846 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2846; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2847 | LOG(("WebSocketChannel::SetupRequest: client key %s\n", secKeyString.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: client key %s\n" , secKeyString.get()); } } while (0); |
2848 | |
2849 | // prepare the value we expect to see in |
2850 | // the sec-websocket-accept response header |
2851 | rv = CalculateWebSocketHashedSecret(secKeyString, mHashedSecret); |
2852 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2852); return rv; } } while (false); |
2853 | LOG(("WebSocketChannel::SetupRequest: expected server key %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: expected server key %s\n" , mHashedSecret.get()); } } while (0) |
2854 | mHashedSecret.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: expected server key %s\n" , mHashedSecret.get()); } } while (0); |
2855 | |
2856 | mHttpChannelId = mHttpChannel->ChannelId(); |
2857 | |
2858 | return NS_OK; |
2859 | } |
2860 | |
2861 | nsresult WebSocketChannel::DoAdmissionDNS() { |
2862 | nsresult rv; |
2863 | |
2864 | nsCString hostName; |
2865 | rv = mURI->GetHost(hostName); |
2866 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2866); return rv; } } while (false); |
2867 | mAddress = hostName; |
2868 | nsCString path; |
2869 | rv = mURI->GetFilePath(path); |
2870 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2870); return rv; } } while (false); |
2871 | mPath = path; |
2872 | rv = mURI->GetPort(&mPort); |
2873 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2873); return rv; } } while (false); |
2874 | if (mPort == -1) mPort = (mEncrypted ? kDefaultWSSPort : kDefaultWSPort); |
2875 | nsCOMPtr<nsIDNSService> dns; |
2876 | dns = mozilla::components::DNS::Service(&rv); |
2877 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2877); return rv; } } while (false); |
2878 | nsCOMPtr<nsIEventTarget> main = GetMainThreadSerialEventTarget(); |
2879 | nsCOMPtr<nsICancelable> cancelable; |
2880 | rv = dns->AsyncResolveNative(hostName, nsIDNSService::RESOLVE_TYPE_DEFAULT, |
2881 | nsIDNSService::RESOLVE_DEFAULT_FLAGS, nullptr, |
2882 | this, main, mLoadInfo->GetOriginAttributes(), |
2883 | getter_AddRefs(cancelable)); |
2884 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2885 | return rv; |
2886 | } |
2887 | |
2888 | MutexAutoLock lock(mMutex); |
2889 | MOZ_ASSERT(!mCancelable)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ")"); do { *((volatile int*)__null) = 2889; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2890 | mCancelable = std::move(cancelable); |
2891 | return rv; |
2892 | } |
2893 | |
2894 | nsresult WebSocketChannel::ApplyForAdmission() { |
2895 | LOG(("WebSocketChannel::ApplyForAdmission() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission() %p\n" , this); } } while (0); |
2896 | |
2897 | // Websockets has a policy of 1 session at a time being allowed in the |
2898 | // CONNECTING state per server IP address (not hostname) |
2899 | |
2900 | // Check to see if a proxy is being used before making DNS call |
2901 | nsCOMPtr<nsIProtocolProxyService> pps; |
2902 | pps = mozilla::components::ProtocolProxy::Service(); |
2903 | |
2904 | if (!pps) { |
2905 | // go straight to DNS |
2906 | // expect the callback in ::OnLookupComplete |
2907 | LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n" ); } } while (0) |
2908 | "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n" ); } } while (0); |
2909 | return DoAdmissionDNS(); |
2910 | } |
2911 | |
2912 | nsresult rv; |
2913 | nsCOMPtr<nsICancelable> cancelable; |
2914 | rv = pps->AsyncResolve( |
2915 | mHttpChannel, |
2916 | nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY | |
2917 | nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY | |
2918 | nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL, |
2919 | this, nullptr, getter_AddRefs(cancelable)); |
2920 | |
2921 | MutexAutoLock lock(mMutex); |
2922 | MOZ_ASSERT(!mCancelable)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ")"); do { *((volatile int*)__null) = 2922; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2923 | mCancelable = std::move(cancelable); |
2924 | return rv; |
2925 | } |
2926 | |
2927 | // Called after both OnStartRequest and OnTransportAvailable have |
2928 | // executed. This essentially ends the handshake and starts the websockets |
2929 | // protocol state machine. |
2930 | nsresult WebSocketChannel::CallStartWebsocketData() { |
2931 | LOG(("WebSocketChannel::CallStartWebsocketData() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallStartWebsocketData() %p" , this); } } while (0); |
2932 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2932; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2933 | |
2934 | if (mOpenTimer) { |
2935 | mOpenTimer->Cancel(); |
2936 | mOpenTimer = nullptr; |
2937 | } |
2938 | |
2939 | nsCOMPtr<nsIEventTarget> target = GetTargetThread(); |
2940 | if (target && !target->IsOnCurrentThread()) { |
2941 | return target->Dispatch( |
2942 | NewRunnableMethod("net::WebSocketChannel::StartWebsocketData", this, |
2943 | &WebSocketChannel::StartWebsocketData), |
2944 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2945 | } |
2946 | |
2947 | return StartWebsocketData(); |
2948 | } |
2949 | |
2950 | nsresult WebSocketChannel::StartWebsocketData() { |
2951 | { |
2952 | MutexAutoLock lock(mMutex); |
2953 | LOG(("WebSocketChannel::StartWebsocketData() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData() %p" , this); } } while (0); |
2954 | MOZ_ASSERT(!mDataStarted, "StartWebsocketData twice")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDataStarted)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDataStarted))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDataStarted" " (" "StartWebsocketData twice" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDataStarted" ") (" "StartWebsocketData twice" ")"); do { *((volatile int* )__null) = 2954; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
2955 | |
2956 | if (mStopped) { |
2957 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not " "starting data"); } } while (0) |
2958 | ("WebSocketChannel::StartWebsocketData channel already closed, not "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not " "starting data"); } } while (0) |
2959 | "starting data"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not " "starting data"); } } while (0); |
2960 | return NS_ERROR_NOT_AVAILABLE; |
2961 | } |
2962 | } |
2963 | |
2964 | RefPtr<WebSocketChannel> self = this; |
2965 | mIOThread->Dispatch(NS_NewRunnableFunction( |
2966 | "WebSocketChannel::StartWebsocketData", [self{std::move(self)}] { |
2967 | LOG(("WebSocketChannel::DoStartWebsocketData() %p", self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStartWebsocketData() %p" , self.get()); } } while (0); |
2968 | |
2969 | NS_DispatchToMainThread( |
2970 | NewRunnableMethod("net::WebSocketChannel::NotifyOnStart", self, |
2971 | &WebSocketChannel::NotifyOnStart), |
2972 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2973 | |
2974 | nsresult rv = self->mConnection ? self->mConnection->StartReading() |
2975 | : self->mSocketIn->AsyncWait( |
2976 | self, 0, 0, self->mIOThread); |
2977 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2978 | self->AbortSession(rv); |
2979 | } |
2980 | |
2981 | if (self->mPingInterval) { |
2982 | rv = self->StartPinging(); |
2983 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2984 | LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0) |
2985 | "WebSocketChannel::StartWebsocketData Could not start pinging, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0) |
2986 | "rv=0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0) |
2987 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0); |
2988 | self->AbortSession(rv); |
2989 | } |
2990 | } |
2991 | })); |
2992 | |
2993 | return NS_OK; |
2994 | } |
2995 | |
2996 | void WebSocketChannel::NotifyOnStart() { |
2997 | LOG(("WebSocketChannel::NotifyOnStart Notifying Listener %p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0) |
2998 | mListenerMT ? mListenerMT->mListener.get() : nullptr))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0); |
2999 | mDataStarted = true; |
3000 | if (mListenerMT) { |
3001 | nsresult rv = mListenerMT->mListener->OnStart(mListenerMT->mContext); |
3002 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3003 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
3004 | ("WebSocketChannel::NotifyOnStart "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
3005 | "mListenerMT->mListener->OnStart() failed with error 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
3006 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0); |
3007 | } |
3008 | } |
3009 | } |
3010 | |
3011 | nsresult WebSocketChannel::StartPinging() { |
3012 | LOG(("WebSocketChannel::StartPinging() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartPinging() %p" , this); } } while (0); |
3013 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3013; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3014 | MOZ_ASSERT(mPingInterval)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPingInterval)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mPingInterval))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mPingInterval", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval" ")"); do { *((volatile int*)__null) = 3014; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3015 | MOZ_ASSERT(!mPingTimer)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mPingTimer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mPingTimer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mPingTimer", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPingTimer" ")"); do { *((volatile int*)__null) = 3015; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3016 | |
3017 | nsresult rv; |
3018 | rv = NS_NewTimerWithCallback(getter_AddRefs(mPingTimer), this, mPingInterval, |
3019 | nsITimer::TYPE_ONE_SHOT); |
3020 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3021 | LOG(("WebSocketChannel will generate ping after %d ms of receive silence\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel will generate ping after %d ms of receive silence\n" , (uint32_t)mPingInterval); } } while (0) |
3022 | (uint32_t)mPingInterval))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel will generate ping after %d ms of receive silence\n" , (uint32_t)mPingInterval); } } while (0); |
3023 | } else { |
3024 | NS_WARNING("unable to create ping timer. Carrying on.")NS_DebugBreak(NS_DEBUG_WARNING, "unable to create ping timer. Carrying on." , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3024); |
3025 | } |
3026 | |
3027 | return NS_OK; |
3028 | } |
3029 | |
3030 | void WebSocketChannel::ReportConnectionTelemetry(nsresult aStatusCode) { |
3031 | // 3 bits are used. high bit is for wss, middle bit for failed, |
3032 | // and low bit for proxy.. |
3033 | // 0 - 7 : ws-ok-plain, ws-ok-proxy, ws-failed-plain, ws-failed-proxy, |
3034 | // wss-ok-plain, wss-ok-proxy, wss-failed-plain, wss-failed-proxy |
3035 | |
3036 | bool didProxy = false; |
3037 | |
3038 | nsCOMPtr<nsIProxyInfo> pi; |
3039 | nsCOMPtr<nsIProxiedChannel> pc = do_QueryInterface(mChannel); |
3040 | if (pc) pc->GetProxyInfo(getter_AddRefs(pi)); |
3041 | if (pi) { |
3042 | nsAutoCString proxyType; |
3043 | pi->GetType(proxyType); |
3044 | if (!proxyType.IsEmpty() && !proxyType.EqualsLiteral("direct")) { |
3045 | didProxy = true; |
3046 | } |
3047 | } |
3048 | |
3049 | uint8_t value = |
3050 | (mEncrypted ? (1 << 2) : 0) | |
3051 | (!(mGotUpgradeOK && NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1) ))) ? (1 << 1) : 0) | |
3052 | (didProxy ? (1 << 0) : 0); |
3053 | |
3054 | LOG(("WebSocketChannel::ReportConnectionTelemetry() %p %d", this, value))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReportConnectionTelemetry() %p %d" , this, value); } } while (0); |
3055 | Telemetry::Accumulate(Telemetry::WEBSOCKETS_HANDSHAKE_TYPE, value); |
3056 | } |
3057 | |
3058 | // nsIDNSListener |
3059 | |
3060 | NS_IMETHODIMPnsresult |
3061 | WebSocketChannel::OnLookupComplete(nsICancelable* aRequest, |
3062 | nsIDNSRecord* aRecord, nsresult aStatus) { |
3063 | LOG(("WebSocketChannel::OnLookupComplete() %p [%p %p %" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete() %p [%p %p %" "x" "]\n", this, aRequest, aRecord, static_cast<uint32_t> (aStatus)); } } while (0) |
3064 | aRequest, aRecord, static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete() %p [%p %p %" "x" "]\n", this, aRequest, aRecord, static_cast<uint32_t> (aStatus)); } } while (0); |
3065 | |
3066 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3066; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3067 | |
3068 | { |
3069 | MutexAutoLock lock(mMutex); |
3070 | mCancelable = nullptr; |
3071 | } |
3072 | |
3073 | if (mStopped) { |
3074 | LOG(("WebSocketChannel::OnLookupComplete: Request Already Stopped\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: Request Already Stopped\n" ); } } while (0); |
3075 | return NS_OK; |
3076 | } |
3077 | |
3078 | // These failures are not fatal - we just use the hostname as the key |
3079 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
3080 | LOG(("WebSocketChannel::OnLookupComplete: No DNS Response\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: No DNS Response\n" ); } } while (0); |
3081 | |
3082 | // set host in case we got here without calling DoAdmissionDNS() |
3083 | mURI->GetHost(mAddress); |
3084 | } else { |
3085 | nsCOMPtr<nsIDNSAddrRecord> record = do_QueryInterface(aRecord); |
3086 | MOZ_ASSERT(record)do { static_assert( mozilla::detail::AssertionConditionType< decltype(record)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(record))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("record", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3086); AnnotateMozCrashReason("MOZ_ASSERT" "(" "record" ")" ); do { *((volatile int*)__null) = 3086; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3087 | nsresult rv = record->GetNextAddrAsString(mAddress); |
3088 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3089 | LOG(("WebSocketChannel::OnLookupComplete: Failed GetNextAddr\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: Failed GetNextAddr\n" ); } } while (0); |
3090 | } |
3091 | } |
3092 | |
3093 | LOG(("WebSocket OnLookupComplete: Proceeding to ConditionallyConnect\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnLookupComplete: Proceeding to ConditionallyConnect\n" ); } } while (0); |
3094 | nsWSAdmissionManager::ConditionallyConnect(this); |
3095 | |
3096 | return NS_OK; |
3097 | } |
3098 | |
3099 | // nsIProtocolProxyCallback |
3100 | NS_IMETHODIMPnsresult |
3101 | WebSocketChannel::OnProxyAvailable(nsICancelable* aRequest, |
3102 | nsIChannel* aChannel, nsIProxyInfo* pi, |
3103 | nsresult status) { |
3104 | { |
3105 | MutexAutoLock lock(mMutex); |
3106 | MOZ_ASSERT(!mCancelable || (aRequest == mCancelable))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable || (aRequest == mCancelable))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mCancelable || (aRequest == mCancelable)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable || (aRequest == mCancelable)" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable || (aRequest == mCancelable)" ")"); do { *((volatile int*)__null) = 3106; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3107 | mCancelable = nullptr; |
3108 | } |
3109 | |
3110 | if (mStopped) { |
3111 | LOG(("WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n" , this); } } while (0) |
3112 | this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n" , this); } } while (0); |
3113 | return NS_OK; |
3114 | } |
3115 | |
3116 | nsAutoCString type; |
3117 | if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && pi && NS_SUCCEEDED(pi->GetType(type))((bool)(__builtin_expect(!!(!NS_FAILED_impl(pi->GetType(type ))), 1))) && |
3118 | !type.EqualsLiteral("direct")) { |
3119 | LOG(("WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n" , this); } } while (0) |
3120 | this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n" , this); } } while (0); |
3121 | // call DNS callback directly without DNS resolver |
3122 | OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); |
3123 | } else { |
3124 | LOG(("WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n" , this); } } while (0) |
3125 | this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n" , this); } } while (0); |
3126 | nsresult rv = DoAdmissionDNS(); |
3127 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3128 | LOG(("WebSocket OnProxyAvailable [%p] DNS lookup failed\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] DNS lookup failed\n" , this); } } while (0); |
3129 | // call DNS callback directly without DNS resolver |
3130 | OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); |
3131 | } |
3132 | } |
3133 | |
3134 | // notify listener of OnProxyAvailable |
3135 | LOG(("WebSocketChannel::OnProxyAvailable Notifying Listener %p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0) |
3136 | mListenerMT ? mListenerMT->mListener.get() : nullptr))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0); |
3137 | nsresult rv; |
3138 | nsCOMPtr<nsIProtocolProxyCallback> ppc( |
3139 | do_QueryInterface(mListenerMT->mListener, &rv)); |
3140 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3141 | rv = ppc->OnProxyAvailable(aRequest, aChannel, pi, status); |
3142 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3143 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0) |
3144 | ("WebSocketChannel::OnProxyAvailable notify"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0) |
3145 | " failed with error 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0) |
3146 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0); |
3147 | } |
3148 | } |
3149 | |
3150 | return NS_OK; |
3151 | } |
3152 | |
3153 | // nsIInterfaceRequestor |
3154 | |
3155 | NS_IMETHODIMPnsresult |
3156 | WebSocketChannel::GetInterface(const nsIID& iid, void** result) { |
3157 | LOG(("WebSocketChannel::GetInterface() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GetInterface() %p\n" , this); } } while (0); |
3158 | |
3159 | if (iid.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::COMTypeInfo<nsIChannelEventSink, void >::kIID))) { |
3160 | return QueryInterface(iid, result); |
3161 | } |
3162 | |
3163 | if (mCallbacks) return mCallbacks->GetInterface(iid, result); |
3164 | |
3165 | return NS_ERROR_NO_INTERFACE; |
3166 | } |
3167 | |
3168 | // nsIChannelEventSink |
3169 | |
3170 | NS_IMETHODIMPnsresult |
3171 | WebSocketChannel::AsyncOnChannelRedirect( |
3172 | nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t flags, |
3173 | nsIAsyncVerifyRedirectCallback* callback) { |
3174 | LOG(("WebSocketChannel::AsyncOnChannelRedirect() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOnChannelRedirect() %p\n" , this); } } while (0); |
3175 | |
3176 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3176; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3177 | |
3178 | nsresult rv; |
3179 | |
3180 | nsCOMPtr<nsIURI> newuri; |
3181 | rv = newChannel->GetURI(getter_AddRefs(newuri)); |
3182 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3182); return rv; } } while (false); |
3183 | |
3184 | // newuri is expected to be http or https |
3185 | bool newuriIsHttps = newuri->SchemeIs("https"); |
3186 | |
3187 | // allow insecure->secure redirects for HTTP Strict Transport Security (from |
3188 | // ws://FOO to https://FOO (mapped to wss://FOO) |
3189 | if (!(flags & (nsIChannelEventSink::REDIRECT_INTERNAL | |
3190 | nsIChannelEventSink::REDIRECT_STS_UPGRADE))) { |
3191 | nsAutoCString newSpec; |
3192 | rv = newuri->GetSpec(newSpec); |
3193 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3193); return rv; } } while (false); |
3194 | |
3195 | LOG(("WebSocketChannel: Redirect to %s denied by configuration\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s denied by configuration\n" , newSpec.get()); } } while (0) |
3196 | newSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s denied by configuration\n" , newSpec.get()); } } while (0); |
3197 | return NS_ERROR_FAILURE; |
3198 | } |
3199 | |
3200 | if (mEncrypted && !newuriIsHttps) { |
3201 | nsAutoCString spec; |
3202 | if (NS_SUCCEEDED(newuri->GetSpec(spec))((bool)(__builtin_expect(!!(!NS_FAILED_impl(newuri->GetSpec (spec))), 1)))) { |
3203 | LOG(("WebSocketChannel: Redirect to %s violates encryption rule\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s violates encryption rule\n" , spec.get()); } } while (0) |
3204 | spec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s violates encryption rule\n" , spec.get()); } } while (0); |
3205 | } |
3206 | return NS_ERROR_FAILURE; |
3207 | } |
3208 | |
3209 | nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(newChannel, &rv); |
3210 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3211 | LOG(("WebSocketChannel: Redirect could not QI to HTTP\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not QI to HTTP\n" ); } } while (0); |
3212 | return rv; |
3213 | } |
3214 | |
3215 | nsCOMPtr<nsIHttpChannelInternal> newUpgradeChannel = |
3216 | do_QueryInterface(newChannel, &rv); |
3217 | |
3218 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3219 | LOG(("WebSocketChannel: Redirect could not QI to HTTP Upgrade\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not QI to HTTP Upgrade\n" ); } } while (0); |
3220 | return rv; |
3221 | } |
3222 | |
3223 | // The redirect is likely OK |
3224 | |
3225 | newChannel->SetNotificationCallbacks(this); |
3226 | |
3227 | mEncrypted = newuriIsHttps; |
3228 | rv = NS_MutateURI(newuri) |
3229 | .SetScheme(mEncrypted ? "wss"_ns : "ws"_ns) |
3230 | .Finalize(mURI); |
3231 | |
3232 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3233 | LOG(("WebSocketChannel: Could not set the proper scheme\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Could not set the proper scheme\n" ); } } while (0); |
3234 | return rv; |
3235 | } |
3236 | |
3237 | mHttpChannel = newHttpChannel; |
3238 | mChannel = newUpgradeChannel; |
3239 | rv = SetupRequest(); |
3240 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3241 | LOG(("WebSocketChannel: Redirect could not SetupRequest()\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not SetupRequest()\n" ); } } while (0); |
3242 | return rv; |
3243 | } |
3244 | |
3245 | // Redirected-to URI may need to be delayed by 1-connecting-per-host and |
3246 | // delay-after-fail algorithms. So hold off calling OnRedirectVerifyCallback |
3247 | // until BeginOpen, when we know it's OK to proceed with new channel. |
3248 | mRedirectCallback = callback; |
3249 | |
3250 | // Mark old channel as successfully connected so we'll clear any FailDelay |
3251 | // associated with the old URI. Note: no need to also call OnStopSession: |
3252 | // it's a no-op for successful, already-connected channels. |
3253 | nsWSAdmissionManager::OnConnected(this); |
3254 | |
3255 | // ApplyForAdmission as if we were starting from fresh... |
3256 | mAddress.Truncate(); |
3257 | mOpenedHttpChannel = false; |
3258 | rv = ApplyForAdmission(); |
3259 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3260 | LOG(("WebSocketChannel: Redirect failed due to DNS failure\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect failed due to DNS failure\n" ); } } while (0); |
3261 | mRedirectCallback = nullptr; |
3262 | return rv; |
3263 | } |
3264 | |
3265 | return NS_OK; |
3266 | } |
3267 | |
3268 | // nsITimerCallback |
3269 | |
3270 | NS_IMETHODIMPnsresult |
3271 | WebSocketChannel::Notify(nsITimer* timer) { |
3272 | LOG(("WebSocketChannel::Notify() %p [%p]\n", this, timer))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Notify() %p [%p]\n" , this, timer); } } while (0); |
3273 | |
3274 | if (timer == mCloseTimer) { |
3275 | MOZ_ASSERT(mClientClosed, "Close Timeout without local close")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mClientClosed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mClientClosed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mClientClosed" " (" "Close Timeout without local close" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientClosed" ") (" "Close Timeout without local close" ")"); do { *((volatile int*)__null) = 3275; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3276 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3276; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3277 | |
3278 | mCloseTimer = nullptr; |
3279 | if (mStopped || mServerClosed) { /* no longer relevant */ |
3280 | return NS_OK; |
3281 | } |
3282 | |
3283 | LOG(("WebSocketChannel:: Expecting Server Close - Timed Out\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Expecting Server Close - Timed Out\n" ); } } while (0); |
3284 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3285 | } else if (timer == mOpenTimer) { |
3286 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3286; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3287 | |
3288 | mOpenTimer = nullptr; |
3289 | LOG(("WebSocketChannel:: Connection Timed Out\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Connection Timed Out\n" ); } } while (0); |
3290 | if (mStopped || mServerClosed) { /* no longer relevant */ |
3291 | return NS_OK; |
3292 | } |
3293 | |
3294 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3295 | MOZ_PUSH_IGNORE_THREAD_SAFETYGCC diagnostic push
GCC diagnostic ignored "-Wthread-safety" |
3296 | // mReconnectDelayTimer is only modified on MainThread, we can read it |
3297 | // without a lock, but ONLY if we're on MainThread! And if we're not |
3298 | // on MainThread, it can't be mReconnectDelayTimer |
3299 | } else if (NS_IsMainThread() && timer == mReconnectDelayTimer) { |
3300 | MOZ_POP_THREAD_SAFETYGCC diagnostic pop |
3301 | MOZ_ASSERT(mConnecting == CONNECTING_DELAYED,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mConnecting == CONNECTING_DELAYED)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mConnecting == CONNECTING_DELAYED ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mConnecting == CONNECTING_DELAYED" " (" "woke up from delay w/o being delayed?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED" ") (" "woke up from delay w/o being delayed?" ")"); do { *(( volatile int*)__null) = 3302; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
3302 | "woke up from delay w/o being delayed?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mConnecting == CONNECTING_DELAYED)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mConnecting == CONNECTING_DELAYED ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mConnecting == CONNECTING_DELAYED" " (" "woke up from delay w/o being delayed?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED" ") (" "woke up from delay w/o being delayed?" ")"); do { *(( volatile int*)__null) = 3302; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
3303 | |
3304 | { |
3305 | MutexAutoLock lock(mMutex); |
3306 | mReconnectDelayTimer = nullptr; |
3307 | } |
3308 | LOG(("WebSocketChannel: connecting [this=%p] after reconnect delay", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: connecting [this=%p] after reconnect delay" , this); } } while (0); |
3309 | BeginOpen(false); |
3310 | } else if (timer == mPingTimer) { |
3311 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3311; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3312 | |
3313 | if (mClientClosed || mServerClosed || mRequestedClose) { |
3314 | // no point in worrying about ping now |
3315 | mPingTimer = nullptr; |
3316 | return NS_OK; |
3317 | } |
3318 | |
3319 | if (!mPingOutstanding) { |
3320 | // Ping interval must be non-null or PING was forced by OnNetworkChanged() |
3321 | MOZ_ASSERT(mPingInterval || mPingForced)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPingInterval || mPingForced)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mPingInterval || mPingForced ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mPingInterval || mPingForced", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval || mPingForced" ")"); do { *((volatile int*)__null) = 3321; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3322 | LOG(("nsWebSocketChannel:: Generating Ping\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Generating Ping\n" ); } } while (0); |
3323 | mPingOutstanding = 1; |
3324 | mPingForced = false; |
3325 | mPingTimer->InitWithCallback(this, mPingResponseTimeout, |
3326 | nsITimer::TYPE_ONE_SHOT); |
3327 | GeneratePing(); |
3328 | } else { |
3329 | LOG(("nsWebSocketChannel:: Timed out Ping\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Timed out Ping\n" ); } } while (0); |
3330 | mPingTimer = nullptr; |
3331 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3332 | } |
3333 | } else if (timer == mLingeringCloseTimer) { |
3334 | LOG(("WebSocketChannel:: Lingering Close Timer"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Lingering Close Timer" ); } } while (0); |
3335 | CleanupConnection(); |
3336 | } else { |
3337 | MOZ_ASSERT(0, "Unknown Timer")do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0" " (" "Unknown Timer" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ") (" "Unknown Timer" ")"); do { *((volatile int*)__null) = 3337; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3338 | } |
3339 | |
3340 | return NS_OK; |
3341 | } |
3342 | |
3343 | // nsINamed |
3344 | |
3345 | NS_IMETHODIMPnsresult |
3346 | WebSocketChannel::GetName(nsACString& aName) { |
3347 | aName.AssignLiteral("WebSocketChannel"); |
3348 | return NS_OK; |
3349 | } |
3350 | |
3351 | // nsIWebSocketChannel |
3352 | |
3353 | NS_IMETHODIMPnsresult |
3354 | WebSocketChannel::GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) { |
3355 | LOG(("WebSocketChannel::GetSecurityInfo() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GetSecurityInfo() %p\n" , this); } } while (0); |
3356 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3356); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3356; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3357 | |
3358 | *aSecurityInfo = nullptr; |
3359 | |
3360 | if (mConnection) { |
3361 | nsresult rv = mConnection->GetSecurityInfo(aSecurityInfo); |
3362 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3363 | return rv; |
3364 | } |
3365 | return NS_OK; |
3366 | } |
3367 | |
3368 | if (mTransport) { |
3369 | nsCOMPtr<nsITLSSocketControl> tlsSocketControl; |
3370 | nsresult rv = |
3371 | mTransport->GetTlsSocketControl(getter_AddRefs(tlsSocketControl)); |
3372 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3373 | return rv; |
3374 | } |
3375 | nsCOMPtr<nsITransportSecurityInfo> securityInfo( |
3376 | do_QueryInterface(tlsSocketControl)); |
3377 | if (securityInfo) { |
3378 | securityInfo.forget(aSecurityInfo); |
3379 | } |
3380 | } |
3381 | return NS_OK; |
3382 | } |
3383 | |
3384 | NS_IMETHODIMPnsresult |
3385 | WebSocketChannel::AsyncOpen(nsIURI* aURI, const nsACString& aOrigin, |
3386 | JS::Handle<JS::Value> aOriginAttributes, |
3387 | uint64_t aInnerWindowID, |
3388 | nsIWebSocketListener* aListener, |
3389 | nsISupports* aContext, JSContext* aCx) { |
3390 | OriginAttributes attrs; |
3391 | if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { |
3392 | return NS_ERROR_INVALID_ARG; |
3393 | } |
3394 | return AsyncOpenNative(aURI, aOrigin, attrs, aInnerWindowID, aListener, |
3395 | aContext); |
3396 | } |
3397 | |
3398 | NS_IMETHODIMPnsresult |
3399 | WebSocketChannel::AsyncOpenNative(nsIURI* aURI, const nsACString& aOrigin, |
3400 | const OriginAttributes& aOriginAttributes, |
3401 | uint64_t aInnerWindowID, |
3402 | nsIWebSocketListener* aListener, |
3403 | nsISupports* aContext) { |
3404 | LOG(("WebSocketChannel::AsyncOpen() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() %p\n" , this); } } while (0); |
3405 | |
3406 | aOriginAttributes.CreateSuffix(mOriginSuffix); |
3407 | |
3408 | if (!NS_IsMainThread()) { |
3409 | MOZ_ASSERT(false, "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3409 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3410 | LOG(("WebSocketChannel::AsyncOpen() called off the main thread"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() called off the main thread" ); } } while (0); |
3411 | return NS_ERROR_UNEXPECTED; |
3412 | } |
3413 | |
3414 | if ((!aURI && !mIsServerSide) || !aListener) { |
3415 | LOG(("WebSocketChannel::AsyncOpen() Uri or Listener null"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() Uri or Listener null" ); } } while (0); |
3416 | return NS_ERROR_UNEXPECTED; |
3417 | } |
3418 | |
3419 | if (mListenerMT || mWasOpened) return NS_ERROR_ALREADY_OPENED; |
3420 | |
3421 | nsresult rv; |
3422 | |
3423 | // Ensure target thread is set if RetargetDeliveryTo isn't called |
3424 | { |
3425 | auto lock = mTargetThread.Lock(); |
3426 | if (!lock.ref()) { |
3427 | lock.ref() = GetMainThreadSerialEventTarget(); |
3428 | } |
3429 | } |
3430 | |
3431 | mIOThread = mozilla::components::SocketTransport::Service(&rv); |
3432 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3433 | NS_WARNING("unable to continue without socket transport service")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without socket transport service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3433); |
3434 | return rv; |
3435 | } |
3436 | |
3437 | nsCOMPtr<nsIPrefBranch> prefService; |
3438 | prefService = mozilla::components::Preferences::Service(); |
3439 | |
3440 | if (prefService) { |
3441 | int32_t intpref; |
3442 | rv = |
3443 | prefService->GetIntPref("network.websocket.max-message-size", &intpref); |
3444 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3445 | mMaxMessageSize = std::clamp(intpref, 1024, INT32_MAX(2147483647)); |
3446 | } |
3447 | rv = prefService->GetIntPref("network.websocket.timeout.close", &intpref); |
3448 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3449 | mCloseTimeout = std::clamp(intpref, 1, 1800) * 1000; |
3450 | } |
3451 | rv = prefService->GetIntPref("network.websocket.timeout.open", &intpref); |
3452 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3453 | mOpenTimeout = std::clamp(intpref, 1, 1800) * 1000; |
3454 | } |
3455 | rv = prefService->GetIntPref("network.websocket.timeout.ping.request", |
3456 | &intpref); |
3457 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingInterval) { |
3458 | mPingInterval = std::clamp(intpref, 0, 86400) * 1000; |
3459 | } |
3460 | rv = prefService->GetIntPref("network.websocket.timeout.ping.response", |
3461 | &intpref); |
3462 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingTimeout) { |
3463 | mPingResponseTimeout = std::clamp(intpref, 1, 3600) * 1000; |
3464 | } |
3465 | rv = prefService->GetIntPref("network.websocket.max-connections", &intpref); |
3466 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3467 | mMaxConcurrentConnections = std::clamp(intpref, 1, 0xffff); |
3468 | } |
3469 | } |
3470 | |
3471 | int32_t sessionCount = -1; |
3472 | nsWSAdmissionManager::GetSessionCount(sessionCount); |
3473 | if (sessionCount >= 0) { |
3474 | LOG(("WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n" , this, sessionCount, mMaxConcurrentConnections); } } while ( 0) |
3475 | sessionCount, mMaxConcurrentConnections))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n" , this, sessionCount, mMaxConcurrentConnections); } } while ( 0); |
3476 | } |
3477 | |
3478 | if (sessionCount >= mMaxConcurrentConnections) { |
3479 | LOG(("WebSocketChannel: max concurrency %d exceeded (%d)",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: max concurrency %d exceeded (%d)" , mMaxConcurrentConnections, sessionCount); } } while (0) |
3480 | mMaxConcurrentConnections, sessionCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: max concurrency %d exceeded (%d)" , mMaxConcurrentConnections, sessionCount); } } while (0); |
3481 | |
3482 | // WebSocket connections are expected to be long lived, so return |
3483 | // an error here instead of queueing |
3484 | return NS_ERROR_SOCKET_CREATE_FAILED; |
3485 | } |
3486 | |
3487 | mInnerWindowID = aInnerWindowID; |
3488 | mOriginalURI = aURI; |
3489 | mURI = mOriginalURI; |
3490 | mOrigin = aOrigin; |
3491 | |
3492 | if (mIsServerSide) { |
3493 | // IncrementSessionCount(); |
3494 | mWasOpened = 1; |
3495 | mListenerMT = new ListenerAndContextContainer(aListener, aContext); |
3496 | rv = mServerTransportProvider->SetListener(this); |
3497 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3497); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3497; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3498 | mServerTransportProvider = nullptr; |
3499 | |
3500 | return NS_OK; |
3501 | } |
3502 | |
3503 | mURI->GetHostPort(mHost); |
3504 | |
3505 | mRandomGenerator = mozilla::components::RandomGenerator::Service(&rv); |
3506 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3507 | NS_WARNING("unable to continue without random number generator")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without random number generator" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3507); |
3508 | return rv; |
3509 | } |
3510 | |
3511 | nsCOMPtr<nsIURI> localURI; |
3512 | nsCOMPtr<nsIChannel> localChannel; |
3513 | |
3514 | rv = NS_MutateURI(mURI) |
3515 | .SetScheme(mEncrypted ? "https"_ns : "http"_ns) |
3516 | .Finalize(localURI); |
3517 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3517); return rv; } } while (false); |
3518 | |
3519 | nsCOMPtr<nsIIOService> ioService; |
3520 | ioService = mozilla::components::IO::Service(&rv); |
3521 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3522 | NS_WARNING("unable to continue without io service")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without io service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3522); |
3523 | return rv; |
3524 | } |
3525 | |
3526 | // Ideally we'd call newChannelFromURIWithLoadInfo here, but that doesn't |
3527 | // allow setting proxy uri/flags |
3528 | rv = ioService->NewChannelFromURIWithProxyFlags( |
3529 | localURI, mURI, |
3530 | nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY | |
3531 | nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY | |
3532 | nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL, |
3533 | mLoadInfo->LoadingNode(), mLoadInfo->GetLoadingPrincipal(), |
3534 | mLoadInfo->TriggeringPrincipal(), mLoadInfo->GetSecurityFlags(), |
3535 | mLoadInfo->InternalContentPolicyType(), getter_AddRefs(localChannel)); |
3536 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3536); return rv; } } while (false); |
3537 | |
3538 | // Please note that we still call SetLoadInfo on the channel because |
3539 | // we want the same instance of the loadInfo to be set on the channel. |
3540 | rv = localChannel->SetLoadInfo(mLoadInfo); |
3541 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3541); return rv; } } while (false); |
3542 | |
3543 | // Pass most GetInterface() requests through to our instantiator, but handle |
3544 | // nsIChannelEventSink in this object in order to deal with redirects |
3545 | localChannel->SetNotificationCallbacks(this); |
3546 | |
3547 | class MOZ_STACK_CLASS CleanUpOnFailure { |
3548 | public: |
3549 | explicit CleanUpOnFailure(WebSocketChannel* aWebSocketChannel) |
3550 | : mWebSocketChannel(aWebSocketChannel) {} |
3551 | |
3552 | ~CleanUpOnFailure() { |
3553 | if (!mWebSocketChannel->mWasOpened) { |
3554 | mWebSocketChannel->mChannel = nullptr; |
3555 | mWebSocketChannel->mHttpChannel = nullptr; |
3556 | } |
3557 | } |
3558 | |
3559 | WebSocketChannel* mWebSocketChannel; |
3560 | }; |
3561 | |
3562 | CleanUpOnFailure cuof(this); |
3563 | |
3564 | mChannel = do_QueryInterface(localChannel, &rv); |
3565 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3565); return rv; } } while (false); |
3566 | |
3567 | mHttpChannel = do_QueryInterface(localChannel, &rv); |
3568 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3568); return rv; } } while (false); |
3569 | |
3570 | rv = SetupRequest(); |
3571 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3572 | |
3573 | mPrivateBrowsing = NS_UsePrivateBrowsing(localChannel); |
3574 | |
3575 | if (mConnectionLogService && !mPrivateBrowsing) { |
3576 | mConnectionLogService->AddHost(mHost, mSerial, |
3577 | BaseWebSocketChannel::mEncrypted); |
3578 | } |
3579 | |
3580 | rv = ApplyForAdmission(); |
3581 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3582 | |
3583 | // Register for prefs change notifications |
3584 | nsCOMPtr<nsIObserverService> observerService = |
3585 | mozilla::services::GetObserverService(); |
3586 | if (!observerService) { |
3587 | NS_WARNING("failed to get observer service")NS_DebugBreak(NS_DEBUG_WARNING, "failed to get observer service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3587); |
3588 | return NS_ERROR_FAILURE; |
3589 | } |
3590 | |
3591 | rv = observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC"network:link-status-changed", false); |
3592 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3592)) { |
3593 | return rv; |
3594 | } |
3595 | |
3596 | // Only set these if the open was successful: |
3597 | // |
3598 | mWasOpened = 1; |
3599 | mListenerMT = new ListenerAndContextContainer(aListener, aContext); |
3600 | IncrementSessionCount(); |
3601 | |
3602 | return rv; |
3603 | } |
3604 | |
3605 | NS_IMETHODIMPnsresult |
3606 | WebSocketChannel::Close(uint16_t code, const nsACString& reason) { |
3607 | LOG(("WebSocketChannel::Close() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() %p\n" , this); } } while (0); |
3608 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3608; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3609 | |
3610 | { |
3611 | MutexAutoLock lock(mMutex); |
3612 | |
3613 | if (mRequestedClose) { |
3614 | return NS_OK; |
3615 | } |
3616 | |
3617 | if (mStopped) { |
3618 | return NS_ERROR_NOT_AVAILABLE; |
3619 | } |
3620 | |
3621 | // The API requires the UTF-8 string to be 123 or less bytes |
3622 | if (reason.Length() > 123) return NS_ERROR_ILLEGAL_VALUE; |
3623 | |
3624 | mRequestedClose = true; |
3625 | mScriptCloseReason = reason; |
3626 | mScriptCloseCode = code; |
3627 | |
3628 | if (mDataStarted) { |
3629 | return mIOThread->Dispatch( |
3630 | new OutboundEnqueuer(this, |
3631 | new OutboundMessage(kMsgTypeFin, VoidCString())), |
3632 | nsIEventTarget::DISPATCH_NORMAL); |
3633 | } |
3634 | |
3635 | mStopped = true; |
3636 | } |
3637 | |
3638 | nsresult rv; |
3639 | if (code == CLOSE_GOING_AWAY) { |
3640 | // Not an error: for example, tab has closed or navigated away |
3641 | LOG(("WebSocketChannel::Close() GOING_AWAY without transport."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() GOING_AWAY without transport." ); } } while (0); |
3642 | rv = NS_OK; |
3643 | } else { |
3644 | LOG(("WebSocketChannel::Close() without transport - error."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() without transport - error." ); } } while (0); |
3645 | rv = NS_ERROR_NOT_CONNECTED; |
3646 | } |
3647 | |
3648 | DoStopSession(rv); |
3649 | return rv; |
3650 | } |
3651 | |
3652 | NS_IMETHODIMPnsresult |
3653 | WebSocketChannel::SendMsg(const nsACString& aMsg) { |
3654 | LOG(("WebSocketChannel::SendMsg() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendMsg() %p\n" , this); } } while (0); |
3655 | |
3656 | return SendMsgCommon(aMsg, false, aMsg.Length()); |
3657 | } |
3658 | |
3659 | NS_IMETHODIMPnsresult |
3660 | WebSocketChannel::SendBinaryMsg(const nsACString& aMsg) { |
3661 | LOG(("WebSocketChannel::SendBinaryMsg() %p len=%zu\n", this, aMsg.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendBinaryMsg() %p len=%zu\n" , this, aMsg.Length()); } } while (0); |
3662 | return SendMsgCommon(aMsg, true, aMsg.Length()); |
3663 | } |
3664 | |
3665 | NS_IMETHODIMPnsresult |
3666 | WebSocketChannel::SendBinaryStream(nsIInputStream* aStream, uint32_t aLength) { |
3667 | LOG(("WebSocketChannel::SendBinaryStream() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendBinaryStream() %p\n" , this); } } while (0); |
3668 | |
3669 | return SendMsgCommon(VoidCString(), true, aLength, aStream); |
3670 | } |
3671 | |
3672 | nsresult WebSocketChannel::SendMsgCommon(const nsACString& aMsg, bool aIsBinary, |
3673 | uint32_t aLength, |
3674 | nsIInputStream* aStream) { |
3675 | MOZ_ASSERT(IsOnTargetThread(), "not target thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsOnTargetThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnTargetThread()" " (" "not target thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnTargetThread()" ") (" "not target thread" ")"); do { *((volatile int*)__null ) = 3675; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3676 | |
3677 | if (!mDataStarted) { |
3678 | LOG(("WebSocketChannel:: Error: data not started yet\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: data not started yet\n" ); } } while (0); |
3679 | return NS_ERROR_UNEXPECTED; |
3680 | } |
3681 | |
3682 | if (mRequestedClose) { |
3683 | LOG(("WebSocketChannel:: Error: send when closed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: send when closed\n" ); } } while (0); |
3684 | return NS_ERROR_UNEXPECTED; |
3685 | } |
3686 | |
3687 | if (mStopped) { |
3688 | LOG(("WebSocketChannel:: Error: send when stopped\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: send when stopped\n" ); } } while (0); |
3689 | return NS_ERROR_NOT_CONNECTED; |
3690 | } |
3691 | |
3692 | MOZ_ASSERT(mMaxMessageSize >= 0, "max message size negative")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMaxMessageSize >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMaxMessageSize >= 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("mMaxMessageSize >= 0" " (" "max message size negative" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3692); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMaxMessageSize >= 0" ") (" "max message size negative" ")"); do { *((volatile int *)__null) = 3692; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3693 | if (aLength > static_cast<uint32_t>(mMaxMessageSize)) { |
3694 | LOG(("WebSocketChannel:: Error: message too big\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: message too big\n" ); } } while (0); |
3695 | return NS_ERROR_FILE_TOO_BIG; |
3696 | } |
3697 | |
3698 | if (mConnectionLogService && !mPrivateBrowsing) { |
3699 | mConnectionLogService->NewMsgSent(mHost, mSerial, aLength); |
3700 | LOG(("Added new msg sent for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new msg sent for %s" , mHost.get()); } } while (0); |
3701 | } |
3702 | |
3703 | return mIOThread->Dispatch( |
3704 | aStream |
3705 | ? new OutboundEnqueuer(this, new OutboundMessage(aStream, aLength)) |
3706 | : new OutboundEnqueuer( |
3707 | this, |
3708 | new OutboundMessage( |
3709 | aIsBinary ? kMsgTypeBinaryString : kMsgTypeString, aMsg)), |
3710 | nsIEventTarget::DISPATCH_NORMAL); |
3711 | } |
3712 | |
3713 | // nsIHttpUpgradeListener |
3714 | |
3715 | NS_IMETHODIMPnsresult |
3716 | WebSocketChannel::OnTransportAvailable(nsISocketTransport* aTransport, |
3717 | nsIAsyncInputStream* aSocketIn, |
3718 | nsIAsyncOutputStream* aSocketOut) { |
3719 | if (!NS_IsMainThread()) { |
3720 | return NS_DispatchToMainThread( |
3721 | new CallOnTransportAvailable(this, aTransport, aSocketIn, aSocketOut)); |
3722 | } |
3723 | |
3724 | LOG(("WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n" , this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK); } } while (0) |
3725 | this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n" , this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK); } } while (0); |
3726 | |
3727 | if (mStopped) { |
3728 | LOG(("WebSocketChannel::OnTransportAvailable: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Already stopped" ); } } while (0); |
3729 | return NS_OK; |
3730 | } |
3731 | |
3732 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3732; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3733 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport, "OTA duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OTA duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OTA duplicated" ")"); do { *((volatile int*)__null) = 3733; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3734 | MOZ_ASSERT(aSocketIn, "OTA with invalid socketIn")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSocketIn)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSocketIn))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSocketIn" " (" "OTA with invalid socketIn" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSocketIn" ") (" "OTA with invalid socketIn" ")"); do { *((volatile int*)__null ) = 3734; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3735 | |
3736 | mTransport = aTransport; |
3737 | mSocketIn = aSocketIn; |
3738 | mSocketOut = aSocketOut; |
3739 | |
3740 | nsresult rv; |
3741 | rv = mTransport->SetEventSink(nullptr, nullptr); |
3742 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3743 | rv = mTransport->SetSecurityCallbacks(this); |
3744 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3745 | |
3746 | return OnTransportAvailableInternal(); |
3747 | } |
3748 | |
3749 | NS_IMETHODIMPnsresult |
3750 | WebSocketChannel::OnWebSocketConnectionAvailable( |
3751 | WebSocketConnectionBase* aConnection) { |
3752 | if (!NS_IsMainThread()) { |
3753 | RefPtr<WebSocketChannel> self = this; |
3754 | RefPtr<WebSocketConnectionBase> connection = aConnection; |
3755 | return NS_DispatchToMainThread(NS_NewRunnableFunction( |
3756 | "WebSocketChannel::OnWebSocketConnectionAvailable", |
3757 | [self, connection]() { |
3758 | self->OnWebSocketConnectionAvailable(connection); |
3759 | })); |
3760 | } |
3761 | |
3762 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0) |
3763 | ("WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0) |
3764 | "rcvdonstart=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0) |
3765 | this, aConnection, mGotUpgradeOK))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0); |
3766 | |
3767 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3767; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3768 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3769; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
3769 | "OnWebSocketConnectionAvailable duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3769; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
3770 | MOZ_ASSERT(aConnection)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aConnection)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aConnection))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aConnection", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aConnection" ")"); do { *((volatile int*)__null) = 3770; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3771 | |
3772 | if (mStopped) { |
3773 | LOG(("WebSocketChannel::OnWebSocketConnectionAvailable: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable: Already stopped" ); } } while (0); |
3774 | aConnection->Close(); |
3775 | return NS_OK; |
3776 | } |
3777 | |
3778 | nsresult rv = aConnection->Init(this); |
3779 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3780 | return rv; |
3781 | } |
3782 | |
3783 | mConnection = aConnection; |
3784 | // Note: mIOThread will be IPDL background thread. |
3785 | mConnection->GetIoTarget(getter_AddRefs(mIOThread)); |
3786 | return OnTransportAvailableInternal(); |
3787 | } |
3788 | |
3789 | nsresult WebSocketChannel::OnTransportAvailableInternal() { |
3790 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3790; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3791 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3792; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
3792 | "OnWebSocketConnectionAvailable duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3792; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
3793 | MOZ_ASSERT(mSocketIn || mConnection)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSocketIn || mConnection)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSocketIn || mConnection))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSocketIn || mConnection" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSocketIn || mConnection" ")"); do { *((volatile int*)__null) = 3793; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3794 | |
3795 | mRecvdHttpUpgradeTransport = 1; |
3796 | if (mGotUpgradeOK) { |
3797 | // We're now done CONNECTING, which means we can now open another, |
3798 | // perhaps parallel, connection to the same host if one |
3799 | // is pending |
3800 | nsWSAdmissionManager::OnConnected(this); |
3801 | |
3802 | return CallStartWebsocketData(); |
3803 | } |
3804 | |
3805 | if (mIsServerSide) { |
3806 | if (!mNegotiatedExtensions.IsEmpty()) { |
3807 | bool clientNoContextTakeover; |
3808 | bool serverNoContextTakeover; |
3809 | int32_t clientMaxWindowBits; |
3810 | int32_t serverMaxWindowBits; |
3811 | |
3812 | nsresult rv = ParseWebSocketExtension( |
3813 | mNegotiatedExtensions, eParseServerSide, clientNoContextTakeover, |
3814 | serverNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits); |
3815 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), "illegal value provided by server")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " (" "illegal value provided by server" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3815); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "illegal value provided by server" ")"); do { *((volatile int*)__null) = 3815; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3816 | |
3817 | if (clientMaxWindowBits == -1) { |
3818 | clientMaxWindowBits = 15; |
3819 | } |
3820 | if (serverMaxWindowBits == -1) { |
3821 | serverMaxWindowBits = 15; |
3822 | } |
3823 | |
3824 | MutexAutoLock lock(mCompressorMutex); |
3825 | mPMCECompressor = MakeUnique<PMCECompression>( |
3826 | serverNoContextTakeover, serverMaxWindowBits, clientMaxWindowBits); |
3827 | if (mPMCECompressor->Active()) { |
3828 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3829 | ("WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3830 | "context takeover, serverMaxWindowBits=%d, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3831 | "clientMaxWindowBits=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3832 | serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3833 | clientMaxWindowBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0); |
3834 | |
3835 | mNegotiatedExtensions = "permessage-deflate"; |
3836 | } else { |
3837 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE " "compression object\n"); } } while (0) |
3838 | ("WebSocketChannel::OnTransportAvailable: Cannot init PMCE "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE " "compression object\n"); } } while (0) |
3839 | "compression object\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE " "compression object\n"); } } while (0); |
3840 | mPMCECompressor = nullptr; |
3841 | AbortSession(NS_ERROR_UNEXPECTED); |
3842 | return NS_ERROR_UNEXPECTED; |
3843 | } |
3844 | } |
3845 | |
3846 | return CallStartWebsocketData(); |
3847 | } |
3848 | |
3849 | return NS_OK; |
3850 | } |
3851 | |
3852 | NS_IMETHODIMPnsresult |
3853 | WebSocketChannel::OnUpgradeFailed(nsresult aErrorCode) { |
3854 | // When socket process is enabled, this could be called on background thread. |
3855 | |
3856 | LOG(("WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %" PRIx32 "]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %" "x" "]", this, static_cast<uint32_t>(aErrorCode)); } } while (0) |
3857 | static_cast<uint32_t>(aErrorCode)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %" "x" "]", this, static_cast<uint32_t>(aErrorCode)); } } while (0); |
3858 | |
3859 | if (mStopped) { |
3860 | LOG(("WebSocketChannel::OnUpgradeFailed: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed: Already stopped" ); } } while (0); |
3861 | return NS_OK; |
3862 | } |
3863 | |
3864 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport, "OTA already called")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OTA already called" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OTA already called" ")"); do { *((volatile int*)__null ) = 3864; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3865 | |
3866 | AbortSession(aErrorCode); |
3867 | return NS_OK; |
3868 | } |
3869 | |
3870 | // nsIRequestObserver (from nsIStreamListener) |
3871 | |
3872 | NS_IMETHODIMPnsresult |
3873 | WebSocketChannel::OnStartRequest(nsIRequest* aRequest) { |
3874 | LOG(("WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n" , this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport ); } } while (0) |
3875 | this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n" , this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport ); } } while (0); |
3876 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3876; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3877 | MOZ_ASSERT(!mGotUpgradeOK, "OTA duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mGotUpgradeOK)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mGotUpgradeOK))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mGotUpgradeOK" " (" "OTA duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mGotUpgradeOK" ") (" "OTA duplicated" ")"); do { *((volatile int*)__null) = 3877; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3878 | |
3879 | if (mStopped) { |
3880 | LOG(("WebSocketChannel::OnStartRequest: Channel Already Done\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Channel Already Done\n" ); } } while (0); |
3881 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
3882 | return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3883 | } |
3884 | |
3885 | nsresult rv; |
3886 | uint32_t status; |
3887 | char *val, *token; |
3888 | |
3889 | rv = mHttpChannel->GetResponseStatus(&status); |
3890 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3891 | nsresult httpStatus; |
3892 | rv = NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3893 | |
3894 | // If we failed to connect due to unsuccessful TLS handshake, we must |
3895 | // propagate a specific error to mozilla::dom::WebSocketImpl so it can set |
3896 | // status code to 1015. Otherwise return |
3897 | // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED. |
3898 | if (NS_SUCCEEDED(mHttpChannel->GetStatus(&httpStatus))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mHttpChannel-> GetStatus(&httpStatus))), 1)))) { |
3899 | uint32_t errorClass; |
3900 | nsCOMPtr<nsINSSErrorsService> errSvc; |
3901 | errSvc = mozilla::components::NSSErrors::Service(); |
3902 | // If GetErrorClass succeeds httpStatus is TLS related failure. |
3903 | if (errSvc && |
3904 | NS_SUCCEEDED(errSvc->GetErrorClass(httpStatus, &errorClass))((bool)(__builtin_expect(!!(!NS_FAILED_impl(errSvc->GetErrorClass (httpStatus, &errorClass))), 1)))) { |
3905 | rv = NS_ERROR_NET_INADEQUATE_SECURITY; |
3906 | } |
3907 | } |
3908 | |
3909 | LOG(("WebSocketChannel::OnStartRequest: No HTTP Response\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: No HTTP Response\n" ); } } while (0); |
3910 | AbortSession(rv); |
3911 | return rv; |
3912 | } |
3913 | |
3914 | LOG(("WebSocketChannel::OnStartRequest: HTTP status %d\n", status))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: HTTP status %d\n" , status); } } while (0); |
3915 | nsCOMPtr<nsIHttpChannelInternal> internalChannel = |
3916 | do_QueryInterface(mHttpChannel); |
3917 | uint32_t versionMajor, versionMinor; |
3918 | rv = internalChannel->GetResponseVersion(&versionMajor, &versionMinor); |
3919 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || |
3920 | !((versionMajor == 1 && versionMinor != 0) || versionMajor == 2) || |
3921 | (versionMajor == 1 && status != 101) || |
3922 | (versionMajor == 2 && status != 200)) { |
3923 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
3924 | return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3925 | } |
3926 | |
3927 | if (versionMajor == 1) { |
3928 | // These are only present on http/1.x websocket upgrades |
3929 | nsAutoCString respUpgrade; |
3930 | rv = mHttpChannel->GetResponseHeader("Upgrade"_ns, respUpgrade); |
3931 | |
3932 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3933 | rv = NS_ERROR_ILLEGAL_VALUE; |
3934 | if (!respUpgrade.IsEmpty()) { |
3935 | val = respUpgrade.BeginWriting(); |
3936 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
3937 | if (nsCRT::strcasecmp(token, "Websocket") == 0) { |
3938 | rv = NS_OK; |
3939 | break; |
3940 | } |
3941 | } |
3942 | } |
3943 | } |
3944 | |
3945 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3946 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Upgrade: websocket not found\n"); } } while (0) |
3947 | ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Upgrade: websocket not found\n"); } } while (0) |
3948 | "HTTP response header Upgrade: websocket not found\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Upgrade: websocket not found\n"); } } while (0); |
3949 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
3950 | return rv; |
3951 | } |
3952 | |
3953 | nsAutoCString respConnection; |
3954 | rv = mHttpChannel->GetResponseHeader("Connection"_ns, respConnection); |
3955 | |
3956 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3957 | rv = NS_ERROR_ILLEGAL_VALUE; |
3958 | if (!respConnection.IsEmpty()) { |
3959 | val = respConnection.BeginWriting(); |
3960 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
3961 | if (nsCRT::strcasecmp(token, "Upgrade") == 0) { |
3962 | rv = NS_OK; |
3963 | break; |
3964 | } |
3965 | } |
3966 | } |
3967 | } |
3968 | |
3969 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3970 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header 'Connection: Upgrade' not found\n"); } } while (0) |
3971 | ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header 'Connection: Upgrade' not found\n"); } } while (0) |
3972 | "HTTP response header 'Connection: Upgrade' not found\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header 'Connection: Upgrade' not found\n"); } } while (0); |
3973 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
3974 | return rv; |
3975 | } |
3976 | |
3977 | nsAutoCString respAccept; |
3978 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Accept"_ns, respAccept); |
3979 | |
3980 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty() || |
3981 | !respAccept.Equals(mHashedSecret)) { |
3982 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Sec-WebSocket-Accept check failed\n"); } } while (0) |
3983 | ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Sec-WebSocket-Accept check failed\n"); } } while (0) |
3984 | "HTTP response header Sec-WebSocket-Accept check failed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Sec-WebSocket-Accept check failed\n"); } } while (0); |
3985 | LOG(("WebSocketChannel::OnStartRequest: Expected %s received %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Expected %s received %s\n" , mHashedSecret.get(), respAccept.get()); } } while (0) |
3986 | mHashedSecret.get(), respAccept.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Expected %s received %s\n" , mHashedSecret.get(), respAccept.get()); } } while (0); |
3987 | #ifdef FUZZING |
3988 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty()) { |
3989 | #endif |
3990 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
3991 | return NS_ERROR_ILLEGAL_VALUE; |
3992 | #ifdef FUZZING |
3993 | } |
3994 | #endif |
3995 | } |
3996 | } |
3997 | |
3998 | // If we sent a sub protocol header, verify the response matches. |
3999 | // If response contains protocol that was not in request, fail. |
4000 | // If response contained no protocol header, set to "" so the protocol |
4001 | // attribute of the WebSocket JS object reflects that |
4002 | if (!mProtocol.IsEmpty()) { |
4003 | nsAutoCString respProtocol; |
4004 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Protocol"_ns, |
4005 | respProtocol); |
4006 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
4007 | rv = NS_ERROR_ILLEGAL_VALUE; |
4008 | val = mProtocol.BeginWriting(); |
4009 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
4010 | if (strcmp(token, respProtocol.get()) == 0) { |
4011 | rv = NS_OK; |
4012 | break; |
4013 | } |
4014 | } |
4015 | |
4016 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
4017 | LOG(("WebsocketChannel::OnStartRequest: subprotocol %s confirmed",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: subprotocol %s confirmed" , respProtocol.get()); } } while (0) |
4018 | respProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: subprotocol %s confirmed" , respProtocol.get()); } } while (0); |
4019 | mProtocol = respProtocol; |
4020 | } else { |
4021 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0) |
4022 | ("WebsocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0) |
4023 | "Server replied with non-matching subprotocol [%s]: aborting",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0) |
4024 | respProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0); |
4025 | mProtocol.Truncate(); |
4026 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
4027 | return NS_ERROR_ILLEGAL_VALUE; |
4028 | } |
4029 | } else { |
4030 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0) |
4031 | ("WebsocketChannel::OnStartRequest "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0) |
4032 | "subprotocol [%s] not found - none returned",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0) |
4033 | mProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0); |
4034 | mProtocol.Truncate(); |
4035 | } |
4036 | } |
4037 | |
4038 | rv = HandleExtensions(); |
4039 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
4040 | |
4041 | // Update mEffectiveURL for off main thread URI access. |
4042 | nsCOMPtr<nsIURI> uri = mURI ? mURI : mOriginalURI; |
4043 | nsAutoCString spec; |
4044 | rv = uri->GetSpec(spec); |
4045 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4045); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 4045; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4046 | CopyUTF8toUTF16(spec, mEffectiveURL); |
4047 | |
4048 | mGotUpgradeOK = 1; |
4049 | if (mRecvdHttpUpgradeTransport) { |
4050 | // We're now done CONNECTING, which means we can now open another, |
4051 | // perhaps parallel, connection to the same host if one |
4052 | // is pending |
4053 | nsWSAdmissionManager::OnConnected(this); |
4054 | |
4055 | return CallStartWebsocketData(); |
4056 | } |
4057 | |
4058 | return NS_OK; |
4059 | } |
4060 | |
4061 | NS_IMETHODIMPnsresult |
4062 | WebSocketChannel::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { |
4063 | LOG(("WebSocketChannel::OnStopRequest() %p [%p %p %" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStopRequest() %p [%p %p %" "x" "]\n", this, aRequest, mHttpChannel.get(), static_cast< uint32_t>(aStatusCode)); } } while (0) |
4064 | aRequest, mHttpChannel.get(), static_cast<uint32_t>(aStatusCode)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStopRequest() %p [%p %p %" "x" "]\n", this, aRequest, mHttpChannel.get(), static_cast< uint32_t>(aStatusCode)); } } while (0); |
4065 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 4065; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4066 | |
4067 | // OnTransportAvailable won't be called if the request is stopped with |
4068 | // an error. Abort the session now instead of waiting for timeout. |
4069 | if (NS_FAILED(aStatusCode)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatusCode)), 0)) ) && !mRecvdHttpUpgradeTransport) { |
4070 | AbortSession(aStatusCode); |
4071 | } |
4072 | |
4073 | ReportConnectionTelemetry(aStatusCode); |
4074 | |
4075 | // This is the end of the HTTP upgrade transaction, the |
4076 | // upgraded streams live on |
4077 | |
4078 | mChannel = nullptr; |
4079 | mHttpChannel = nullptr; |
4080 | mLoadGroup = nullptr; |
4081 | mCallbacks = nullptr; |
4082 | |
4083 | return NS_OK; |
4084 | } |
4085 | |
4086 | // nsIInputStreamCallback |
4087 | |
4088 | NS_IMETHODIMPnsresult |
4089 | WebSocketChannel::OnInputStreamReady(nsIAsyncInputStream* aStream) { |
4090 | LOG(("WebSocketChannel::OnInputStreamReady() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady() %p\n" , this); } } while (0); |
4091 | MOZ_DIAGNOSTIC_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4091); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4091; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4092 | |
4093 | if (!mSocketIn) { // did we we clean up the socket after scheduling |
4094 | // InputReady? |
4095 | return NS_OK; |
4096 | } |
4097 | |
4098 | // this is after the http upgrade - so we are speaking websockets |
4099 | char buffer[2048]; |
4100 | uint32_t count; |
4101 | nsresult rv; |
4102 | |
4103 | do { |
4104 | rv = mSocketIn->Read((char*)buffer, sizeof(buffer), &count); |
4105 | LOG(("WebSocketChannel::OnInputStreamReady: read %u rv %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady: read %u rv %" "x" "\n", count, static_cast<uint32_t>(rv)); } } while (0) |
4106 | count, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady: read %u rv %" "x" "\n", count, static_cast<uint32_t>(rv)); } } while (0); |
4107 | |
4108 | if (rv == NS_BASE_STREAM_WOULD_BLOCK) { |
4109 | mSocketIn->AsyncWait(this, 0, 0, mIOThread); |
4110 | return NS_OK; |
4111 | } |
4112 | |
4113 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4114 | AbortSession(rv); |
4115 | return rv; |
4116 | } |
4117 | |
4118 | if (count == 0) { |
4119 | AbortSession(NS_BASE_STREAM_CLOSED); |
4120 | return NS_OK; |
4121 | } |
4122 | |
4123 | if (mStopped) { |
4124 | continue; |
4125 | } |
4126 | |
4127 | rv = ProcessInput((uint8_t*)buffer, count); |
4128 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4129 | AbortSession(rv); |
4130 | return rv; |
4131 | } |
4132 | } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mSocketIn); |
4133 | |
4134 | return NS_OK; |
4135 | } |
4136 | |
4137 | // nsIOutputStreamCallback |
4138 | |
4139 | NS_IMETHODIMPnsresult |
4140 | WebSocketChannel::OnOutputStreamReady(nsIAsyncOutputStream* aStream) { |
4141 | LOG(("WebSocketChannel::OnOutputStreamReady() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady() %p\n" , this); } } while (0); |
4142 | MOZ_DIAGNOSTIC_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4142); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4142; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4143 | nsresult rv; |
4144 | |
4145 | if (!mCurrentOut) PrimeNewOutgoingMessage(); |
4146 | |
4147 | while (mCurrentOut && mSocketOut) { |
4148 | const char* sndBuf; |
4149 | uint32_t toSend; |
4150 | uint32_t amtSent; |
4151 | |
4152 | if (mHdrOut) { |
4153 | sndBuf = (const char*)mHdrOut; |
4154 | toSend = mHdrOutToSend; |
4155 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0) |
4156 | ("WebSocketChannel::OnOutputStreamReady: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0) |
4157 | "Try to send %u of hdr/copybreak\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0) |
4158 | toSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0); |
4159 | } else { |
4160 | sndBuf = (char*)mCurrentOut->BeginReading() + mCurrentOutSent; |
4161 | toSend = mCurrentOut->Length() - mCurrentOutSent; |
4162 | if (toSend > 0) { |
4163 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0) |
4164 | ("WebSocketChannel::OnOutputStreamReady [%p]: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0) |
4165 | "Try to send %u of data\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0) |
4166 | this, toSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0); |
4167 | } |
4168 | } |
4169 | |
4170 | if (toSend == 0) { |
4171 | amtSent = 0; |
4172 | } else { |
4173 | rv = mSocketOut->Write(sndBuf, toSend, &amtSent); |
4174 | LOG(("WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" "x" "\n", this, amtSent, static_cast<uint32_t>(rv)); } } while (0) |
4175 | "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" "x" "\n", this, amtSent, static_cast<uint32_t>(rv)); } } while (0) |
4176 | this, amtSent, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" "x" "\n", this, amtSent, static_cast<uint32_t>(rv)); } } while (0); |
4177 | |
4178 | if (rv == NS_BASE_STREAM_WOULD_BLOCK) { |
4179 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4180 | return NS_OK; |
4181 | } |
4182 | |
4183 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4184 | AbortSession(rv); |
4185 | return NS_OK; |
4186 | } |
4187 | } |
4188 | |
4189 | if (mHdrOut) { |
4190 | if (amtSent == toSend) { |
4191 | mHdrOut = nullptr; |
4192 | mHdrOutToSend = 0; |
4193 | } else { |
4194 | mHdrOut += amtSent; |
4195 | mHdrOutToSend -= amtSent; |
4196 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4197 | } |
4198 | } else { |
4199 | if (amtSent == toSend) { |
4200 | if (!mStopped) { |
4201 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
4202 | target->Dispatch( |
4203 | new CallAcknowledge(this, mCurrentOut->OrigLength()), |
4204 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
4205 | } else { |
4206 | return NS_ERROR_UNEXPECTED; |
4207 | } |
4208 | } |
4209 | DeleteCurrentOutGoingMessage(); |
4210 | PrimeNewOutgoingMessage(); |
4211 | } else { |
4212 | mCurrentOutSent += amtSent; |
4213 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4214 | } |
4215 | } |
4216 | } |
4217 | |
4218 | if (mReleaseOnTransmit) ReleaseSession(); |
4219 | return NS_OK; |
4220 | } |
4221 | |
4222 | // nsIStreamListener |
4223 | |
4224 | NS_IMETHODIMPnsresult |
4225 | WebSocketChannel::OnDataAvailable(nsIRequest* aRequest, |
4226 | nsIInputStream* aInputStream, |
4227 | uint64_t aOffset, uint32_t aCount) { |
4228 | LOG(("WebSocketChannel::OnDataAvailable() %p [%p %p %p %" PRIu64 " %u]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable() %p [%p %p %p %" "l" "u" " %u]\n", this, aRequest, mHttpChannel.get(), aInputStream , aOffset, aCount); } } while (0) |
4229 | this, aRequest, mHttpChannel.get(), aInputStream, aOffset, aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable() %p [%p %p %p %" "l" "u" " %u]\n", this, aRequest, mHttpChannel.get(), aInputStream , aOffset, aCount); } } while (0); |
4230 | |
4231 | // This is the HTTP OnDataAvailable Method, which means this is http data in |
4232 | // response to the upgrade request and there should be no http response body |
4233 | // if the upgrade succeeded. This generally should be caught by a non 101 |
4234 | // response code in OnStartRequest().. so we can ignore the data here |
4235 | |
4236 | LOG(("WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n" , aCount); } } while (0) |
4237 | aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n" , aCount); } } while (0); |
4238 | |
4239 | return NS_OK; |
4240 | } |
4241 | |
4242 | void WebSocketChannel::DoEnqueueOutgoingMessage() { |
4243 | LOG(("WebSocketChannel::DoEnqueueOutgoingMessage() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage() %p\n" , this); } } while (0); |
4244 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4244; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4245 | |
4246 | if (!mCurrentOut) { |
4247 | PrimeNewOutgoingMessage(); |
4248 | } |
4249 | |
4250 | while (mCurrentOut && mConnection) { |
4251 | nsresult rv = NS_OK; |
4252 | if (mCurrentOut->Length() - mCurrentOutSent == 0) { |
4253 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0) |
4254 | ("WebSocketChannel::DoEnqueueOutgoingMessage: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0) |
4255 | "Try to send %u of hdr/copybreak\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0) |
4256 | mHdrOutToSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0); |
4257 | rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, nullptr, 0); |
4258 | } else { |
4259 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0) |
4260 | ("WebSocketChannel::DoEnqueueOutgoingMessage: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0) |
4261 | "Try to send %u of hdr and %u of data\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0) |
4262 | mHdrOutToSend, mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0); |
4263 | rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, |
4264 | (uint8_t*)mCurrentOut->BeginReading(), |
4265 | mCurrentOut->Length()); |
4266 | } |
4267 | |
4268 | LOG(("WebSocketChannel::DoEnqueueOutgoingMessage: rv %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: rv %" "x" "\n", static_cast<uint32_t>(rv)); } } while (0) |
4269 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: rv %" "x" "\n", static_cast<uint32_t>(rv)); } } while (0); |
4270 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4271 | AbortSession(rv); |
4272 | return; |
4273 | } |
4274 | |
4275 | if (!mStopped) { |
4276 | // TODO: Currently, we assume that data is completely written to the |
4277 | // socket after sending it to socket process, but it's not true. The data |
4278 | // could be queued in socket process and waiting for the socket to be able |
4279 | // to write. We should implement flow control for this in bug 1726552. |
4280 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
4281 | target->Dispatch(new CallAcknowledge(this, mCurrentOut->OrigLength()), |
4282 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
4283 | } else { |
4284 | AbortSession(NS_ERROR_UNEXPECTED); |
4285 | return; |
4286 | } |
4287 | } |
4288 | DeleteCurrentOutGoingMessage(); |
4289 | PrimeNewOutgoingMessage(); |
4290 | } |
4291 | |
4292 | if (mReleaseOnTransmit) { |
4293 | ReleaseSession(); |
4294 | } |
4295 | } |
4296 | |
4297 | void WebSocketChannel::OnError(nsresult aStatus) { AbortSession(aStatus); } |
4298 | |
4299 | void WebSocketChannel::OnTCPClosed() { mTCPClosed = true; } |
4300 | |
4301 | nsresult WebSocketChannel::OnDataReceived(uint8_t* aData, uint32_t aCount) { |
4302 | return ProcessInput(aData, aCount); |
4303 | } |
4304 | |
4305 | } // namespace mozilla::net |
4306 | |
4307 | #undef CLOSE_GOING_AWAY |