File: | var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp |
Warning: | line 2677, column 3 Value stored to 'rv' is never read |
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 "nsAlgorithm.h" |
28 | #include "nsCRT.h" |
29 | #include "nsCharSeparatedTokenizer.h" |
30 | #include "nsComponentManagerUtils.h" |
31 | #include "nsError.h" |
32 | #include "nsIAsyncVerifyRedirectCallback.h" |
33 | #include "nsICancelable.h" |
34 | #include "nsIChannel.h" |
35 | #include "nsIClassOfService.h" |
36 | #include "nsICryptoHash.h" |
37 | #include "nsIDNSRecord.h" |
38 | #include "nsIDNSService.h" |
39 | #include "nsIDashboardEventNotifier.h" |
40 | #include "nsIEventTarget.h" |
41 | #include "nsIHttpChannel.h" |
42 | #include "nsIIOService.h" |
43 | #include "nsINSSErrorsService.h" |
44 | #include "nsINetworkLinkService.h" |
45 | #include "nsINode.h" |
46 | #include "nsIObserverService.h" |
47 | #include "nsIPrefBranch.h" |
48 | #include "nsIProtocolHandler.h" |
49 | #include "nsIProtocolProxyService.h" |
50 | #include "nsIProxiedChannel.h" |
51 | #include "nsIProxyInfo.h" |
52 | #include "nsIRandomGenerator.h" |
53 | #include "nsIRunnable.h" |
54 | #include "nsISocketTransport.h" |
55 | #include "nsITLSSocketControl.h" |
56 | #include "nsITransportProvider.h" |
57 | #include "nsITransportSecurityInfo.h" |
58 | #include "nsIURI.h" |
59 | #include "nsIURIMutator.h" |
60 | #include "nsNetCID.h" |
61 | #include "nsNetUtil.h" |
62 | #include "nsProxyRelease.h" |
63 | #include "nsServiceManagerUtils.h" |
64 | #include "nsSocketTransportService2.h" |
65 | #include "nsStringStream.h" |
66 | #include "nsThreadUtils.h" |
67 | #include "plbase64.h" |
68 | #include "prmem.h" |
69 | #include "prnetdb.h" |
70 | #include "zlib.h" |
71 | |
72 | // rather than slurp up all of nsIWebSocket.idl, which lives outside necko, just |
73 | // dupe one constant we need from it |
74 | #define CLOSE_GOING_AWAY 1001 |
75 | |
76 | using namespace mozilla; |
77 | using namespace mozilla::net; |
78 | |
79 | namespace mozilla::net { |
80 | |
81 | 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" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 86 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof (table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
82 | nsIRequestObserver, nsIStreamListener, nsIProtocolHandler,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 86 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof (table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
83 | nsIInputStreamCallback, nsIOutputStreamCallback,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 86 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof (table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
84 | nsITimerCallback, nsIDNSListener, nsIProtocolProxyCallback,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 86 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof (table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
85 | nsIInterfaceRequestor, nsIChannelEventSink,MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 86 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof (table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
86 | nsIThreadRetargetableRequest, nsIObserver, nsINamed)MozExternalRefCountType WebSocketChannel::AddRef(void) { static_assert (!std::is_destructible_v<WebSocketChannel>, "Reference-counted class " "WebSocketChannel" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("WebSocketChannel"), (uint32_t )(sizeof(*this))); return count; } MozExternalRefCountType WebSocketChannel ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 86 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("WebSocketChannel" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("WebSocketChannel" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"WebSocketChannel\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WebSocketChannel\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 86; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("WebSocketChannel" " not thread-safe"); const char* const nametmp = "WebSocketChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease ((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult WebSocketChannel ::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 86); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(15 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsIWebSocketChannel> , int32_t( reinterpret_cast<char*>(static_cast<nsIWebSocketChannel *>((WebSocketChannel*)0x1000)) - reinterpret_cast<char* >((WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIHttpUpgradeListener>, int32_t( reinterpret_cast <char*>(static_cast<nsIHttpUpgradeListener*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIRequestObserver>, int32_t( reinterpret_cast<char*> (static_cast<nsIRequestObserver*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIStreamListener>, int32_t( reinterpret_cast<char*> (static_cast<nsIStreamListener*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolHandler>, int32_t( reinterpret_cast<char*> (static_cast<nsIProtocolHandler*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIInputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIOutputStreamCallback>, int32_t( reinterpret_cast<char *>(static_cast<nsIOutputStreamCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsITimerCallback>, int32_t( reinterpret_cast<char*> (static_cast<nsITimerCallback*>((WebSocketChannel*)0x1000 )) - reinterpret_cast<char*>((WebSocketChannel*)0x1000) )}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIDNSListener>, int32_t( reinterpret_cast<char*>( static_cast<nsIDNSListener*>((WebSocketChannel*)0x1000) ) - reinterpret_cast<char*>((WebSocketChannel*)0x1000)) }, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIProtocolProxyCallback>, int32_t( reinterpret_cast< char*>(static_cast<nsIProtocolProxyCallback*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIInterfaceRequestor>, int32_t( reinterpret_cast<char *>(static_cast<nsIInterfaceRequestor*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIChannelEventSink>, int32_t( reinterpret_cast<char* >(static_cast<nsIChannelEventSink*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsIThreadRetargetableRequest>, int32_t( reinterpret_cast <char*>(static_cast<nsIThreadRetargetableRequest*> ((WebSocketChannel*)0x1000)) - reinterpret_cast<char*>( (WebSocketChannel*)0x1000))}, {&mozilla::detail::kImplementedIID <WebSocketChannel, nsIObserver>, int32_t( reinterpret_cast <char*>(static_cast<nsIObserver*>((WebSocketChannel *)0x1000)) - reinterpret_cast<char*>((WebSocketChannel* )0x1000))}, {&mozilla::detail::kImplementedIID<WebSocketChannel , nsINamed>, int32_t( reinterpret_cast<char*>(static_cast <nsINamed*>((WebSocketChannel*)0x1000)) - reinterpret_cast <char*>((WebSocketChannel*)0x1000))}, {&mozilla::detail ::kImplementedIID<WebSocketChannel, nsISupports>, int32_t (reinterpret_cast<char*>(static_cast<nsISupports*> ( static_cast<nsIWebSocketChannel*>((WebSocketChannel*) 0x1000))) - reinterpret_cast<char*>((WebSocketChannel*) 0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof (table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
87 | |
88 | // We implement RFC 6455, which uses Sec-WebSocket-Version: 13 on the wire. |
89 | #define SEC_WEBSOCKET_VERSION"13" "13" |
90 | |
91 | /* |
92 | * About SSL unsigned certificates |
93 | * |
94 | * wss will not work to a host using an unsigned certificate unless there |
95 | * is already an exception (i.e. it cannot popup a dialog asking for |
96 | * a security exception). This is similar to how an inlined img will |
97 | * fail without a dialog if fails for the same reason. This should not |
98 | * be a problem in practice as it is expected the websocket javascript |
99 | * is served from the same host as the websocket server (or of course, |
100 | * a valid cert could just be provided). |
101 | * |
102 | */ |
103 | |
104 | // some helper classes |
105 | |
106 | //----------------------------------------------------------------------------- |
107 | // FailDelayManager |
108 | // |
109 | // Stores entries (searchable by {host, port}) of connections that have recently |
110 | // failed, so we can do delay of reconnects per RFC 6455 Section 7.2.3 |
111 | //----------------------------------------------------------------------------- |
112 | |
113 | // Initial reconnect delay is randomly chosen between 200-400 ms. |
114 | // This is a gentler backoff than the 0-5 seconds the spec offhandedly suggests. |
115 | const uint32_t kWSReconnectInitialBaseDelay = 200; |
116 | const uint32_t kWSReconnectInitialRandomDelay = 200; |
117 | |
118 | // Base lifetime (in ms) of a FailDelay: kept longer if more failures occur |
119 | const uint32_t kWSReconnectBaseLifeTime = 60 * 1000; |
120 | // Maximum reconnect delay (in ms) |
121 | const uint32_t kWSReconnectMaxDelay = 60 * 1000; |
122 | |
123 | // hold record of failed connections, and calculates needed delay for reconnects |
124 | // to same host/path/port. |
125 | class FailDelay { |
126 | public: |
127 | FailDelay(nsCString address, nsCString path, int32_t port) |
128 | : mAddress(std::move(address)), mPath(std::move(path)), mPort(port) { |
129 | mLastFailure = TimeStamp::Now(); |
130 | mNextDelay = kWSReconnectInitialBaseDelay + |
131 | (rand() % kWSReconnectInitialRandomDelay); |
132 | } |
133 | |
134 | // Called to update settings when connection fails again. |
135 | void FailedAgain() { |
136 | mLastFailure = TimeStamp::Now(); |
137 | // We use a truncated exponential backoff as suggested by RFC 6455, |
138 | // but multiply by 1.5 instead of 2 to be more gradual. |
139 | mNextDelay = static_cast<uint32_t>( |
140 | std::min<double>(kWSReconnectMaxDelay, mNextDelay * 1.5)); |
141 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
142 | ("WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
143 | "to "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
144 | "%" PRIu32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0) |
145 | mAddress.get(), mPath.get(), mPort, mNextDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: FailedAgain: host=%s, path=%s, port=%d: incremented delay " "to " "%" "u", mAddress.get(), mPath.get(), mPort, mNextDelay ); } } while (0); |
146 | } |
147 | |
148 | // returns 0 if there is no need to delay (i.e. delay interval is over) |
149 | uint32_t RemainingDelay(TimeStamp rightNow) { |
150 | TimeDuration dur = rightNow - mLastFailure; |
151 | uint32_t sinceFail = (uint32_t)dur.ToMilliseconds(); |
152 | if (sinceFail > mNextDelay) return 0; |
153 | |
154 | return mNextDelay - sinceFail; |
155 | } |
156 | |
157 | bool IsExpired(TimeStamp rightNow) { |
158 | return (mLastFailure + TimeDuration::FromMilliseconds( |
159 | kWSReconnectBaseLifeTime + mNextDelay)) <= |
160 | rightNow; |
161 | } |
162 | |
163 | nsCString mAddress; // IP address (or hostname if using proxy) |
164 | nsCString mPath; |
165 | int32_t mPort; |
166 | |
167 | private: |
168 | TimeStamp mLastFailure; // Time of last failed attempt |
169 | // mLastFailure + mNextDelay is the soonest we'll allow a reconnect |
170 | uint32_t mNextDelay; // milliseconds |
171 | }; |
172 | |
173 | class FailDelayManager { |
174 | public: |
175 | FailDelayManager() { |
176 | MOZ_COUNT_CTOR(FailDelayManager)do { static_assert(std::is_class_v<FailDelayManager>, "Token '" "FailDelayManager" "' is not a class type."); static_assert( !std::is_base_of<nsISupports, FailDelayManager>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR" );; NS_LogCtor((void*)this, "FailDelayManager", sizeof(*this) ); } while (0); |
177 | |
178 | mDelaysDisabled = false; |
179 | |
180 | nsCOMPtr<nsIPrefBranch> prefService; |
181 | prefService = mozilla::components::Preferences::Service(); |
182 | if (!prefService) { |
183 | return; |
184 | } |
185 | bool boolpref = true; |
186 | nsresult rv; |
187 | rv = prefService->GetBoolPref("network.websocket.delay-failed-reconnects", |
188 | &boolpref); |
189 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !boolpref) { |
190 | mDelaysDisabled = true; |
191 | } |
192 | } |
193 | |
194 | ~FailDelayManager() { MOZ_COUNT_DTOR(FailDelayManager)do { static_assert(std::is_class_v<FailDelayManager>, "Token '" "FailDelayManager" "' is not a class type."); static_assert( !std::is_base_of<nsISupports, FailDelayManager>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR" );; NS_LogDtor((void*)this, "FailDelayManager", sizeof(*this) ); } while (0); } |
195 | |
196 | void Add(nsCString& address, nsCString& path, int32_t port) { |
197 | if (mDelaysDisabled) return; |
198 | |
199 | UniquePtr<FailDelay> record(new FailDelay(address, path, port)); |
200 | mEntries.AppendElement(std::move(record)); |
201 | } |
202 | |
203 | // Element returned may not be valid after next main thread event: don't keep |
204 | // pointer to it around |
205 | FailDelay* Lookup(nsCString& address, nsCString& path, int32_t port, |
206 | uint32_t* outIndex = nullptr) { |
207 | if (mDelaysDisabled) return nullptr; |
208 | |
209 | FailDelay* result = nullptr; |
210 | TimeStamp rightNow = TimeStamp::Now(); |
211 | |
212 | // We also remove expired entries during search: iterate from end to make |
213 | // indexing simpler |
214 | for (int32_t i = mEntries.Length() - 1; i >= 0; --i) { |
215 | FailDelay* fail = mEntries[i].get(); |
216 | if (fail->mAddress.Equals(address) && fail->mPath.Equals(path) && |
217 | fail->mPort == port) { |
218 | if (outIndex) *outIndex = i; |
219 | result = fail; |
220 | // break here: removing more entries would mess up *outIndex. |
221 | // Any remaining expired entries will be deleted next time Lookup |
222 | // finds nothing, which is the most common case anyway. |
223 | break; |
224 | } |
225 | if (fail->IsExpired(rightNow)) { |
226 | mEntries.RemoveElementAt(i); |
227 | } |
228 | } |
229 | return result; |
230 | } |
231 | |
232 | // returns true if channel connects immediately, or false if it's delayed |
233 | void DelayOrBegin(WebSocketChannel* ws) { |
234 | if (!mDelaysDisabled) { |
235 | uint32_t failIndex = 0; |
236 | FailDelay* fail = Lookup(ws->mAddress, ws->mPath, ws->mPort, &failIndex); |
237 | |
238 | if (fail) { |
239 | TimeStamp rightNow = TimeStamp::Now(); |
240 | |
241 | uint32_t remainingDelay = fail->RemainingDelay(rightNow); |
242 | if (remainingDelay) { |
243 | // reconnecting within delay interval: delay by remaining time |
244 | nsresult rv; |
245 | MutexAutoLock lock(ws->mMutex); |
246 | rv = NS_NewTimerWithCallback(getter_AddRefs(ws->mReconnectDelayTimer), |
247 | ws, remainingDelay, |
248 | nsITimer::TYPE_ONE_SHOT); |
249 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
250 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0) |
251 | ("WebSocket: delaying websocket [this=%p] by %lu ms, changing"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0) |
252 | " state to CONNECTING_DELAYED",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0) |
253 | ws, (unsigned long)remainingDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: delaying websocket [this=%p] by %lu ms, changing" " state to CONNECTING_DELAYED", ws, (unsigned long)remainingDelay ); } } while (0); |
254 | ws->mConnecting = CONNECTING_DELAYED; |
255 | return; |
256 | } |
257 | // if timer fails (which is very unlikely), drop down to BeginOpen |
258 | // call |
259 | } else if (fail->IsExpired(rightNow)) { |
260 | mEntries.RemoveElementAt(failIndex); |
261 | } |
262 | } |
263 | } |
264 | |
265 | // Delays disabled, or no previous failure, or we're reconnecting after |
266 | // scheduled delay interval has passed: connect. |
267 | ws->BeginOpen(true); |
268 | } |
269 | |
270 | // Remove() also deletes all expired entries as it iterates: better for |
271 | // battery life than using a periodic timer. |
272 | void Remove(nsCString& address, nsCString& path, int32_t port) { |
273 | TimeStamp rightNow = TimeStamp::Now(); |
274 | |
275 | // iterate from end, to make deletion indexing easier |
276 | for (int32_t i = mEntries.Length() - 1; i >= 0; --i) { |
277 | FailDelay* entry = mEntries[i].get(); |
278 | if ((entry->mAddress.Equals(address) && entry->mPath.Equals(path) && |
279 | entry->mPort == port) || |
280 | entry->IsExpired(rightNow)) { |
281 | mEntries.RemoveElementAt(i); |
282 | } |
283 | } |
284 | } |
285 | |
286 | private: |
287 | nsTArray<UniquePtr<FailDelay>> mEntries; |
288 | bool mDelaysDisabled; |
289 | }; |
290 | |
291 | //----------------------------------------------------------------------------- |
292 | // nsWSAdmissionManager |
293 | // |
294 | // 1) Ensures that only one websocket at a time is CONNECTING to a given IP |
295 | // address (or hostname, if using proxy), per RFC 6455 Section 4.1. |
296 | // 2) Delays reconnects to IP/host after connection failure, per Section 7.2.3 |
297 | //----------------------------------------------------------------------------- |
298 | |
299 | class nsWSAdmissionManager { |
300 | public: |
301 | static void Init() { |
302 | StaticMutexAutoLock lock(sLock); |
303 | if (!sManager) { |
304 | sManager = new nsWSAdmissionManager(); |
305 | } |
306 | } |
307 | |
308 | static void Shutdown() { |
309 | StaticMutexAutoLock lock(sLock); |
310 | delete sManager; |
311 | sManager = nullptr; |
312 | } |
313 | |
314 | // Determine if we will open connection immediately (returns true), or |
315 | // delay/queue the connection (returns false) |
316 | static void ConditionallyConnect(WebSocketChannel* ws) { |
317 | LOG(("Websocket: ConditionallyConnect: [this=%p]", ws))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: ConditionallyConnect: [this=%p]" , ws); } } while (0); |
318 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 318; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
319 | MOZ_ASSERT(ws->mConnecting == NOT_CONNECTING, "opening state")do { static_assert( mozilla::detail::AssertionConditionType< decltype(ws->mConnecting == NOT_CONNECTING)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(ws->mConnecting == NOT_CONNECTING ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "ws->mConnecting == NOT_CONNECTING" " (" "opening state" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ws->mConnecting == NOT_CONNECTING" ") (" "opening state" ")"); do { *((volatile int*)__null) = 319 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
320 | |
321 | StaticMutexAutoLock lock(sLock); |
322 | if (!sManager) { |
323 | return; |
324 | } |
325 | |
326 | // If there is already another WS channel connecting to this IP address, |
327 | // defer BeginOpen and mark as waiting in queue. |
328 | bool hostFound = (sManager->IndexOf(ws->mAddress, ws->mOriginSuffix) >= 0); |
329 | |
330 | uint32_t failIndex = 0; |
331 | FailDelay* fail = sManager->mFailures.Lookup(ws->mAddress, ws->mPath, |
332 | ws->mPort, &failIndex); |
333 | bool existingFail = fail != nullptr; |
334 | |
335 | // Always add ourselves to queue, even if we'll connect immediately |
336 | UniquePtr<nsOpenConn> newdata( |
337 | new nsOpenConn(ws->mAddress, ws->mOriginSuffix, existingFail, ws)); |
338 | |
339 | // If a connection has not previously failed then prioritize it over |
340 | // connections that have |
341 | if (existingFail) { |
342 | sManager->mQueue.AppendElement(std::move(newdata)); |
343 | } else { |
344 | uint32_t insertionIndex = sManager->IndexOfFirstFailure(); |
345 | MOZ_ASSERT(insertionIndex <= sManager->mQueue.Length(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(insertionIndex <= sManager->mQueue.Length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(insertionIndex <= sManager->mQueue.Length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("insertionIndex <= sManager->mQueue.Length()" " (" "Insertion index outside bounds" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()" ") (" "Insertion index outside bounds" ")"); do { *((volatile int*)__null) = 346; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
346 | "Insertion index outside bounds")do { static_assert( mozilla::detail::AssertionConditionType< decltype(insertionIndex <= sManager->mQueue.Length())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(insertionIndex <= sManager->mQueue.Length()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("insertionIndex <= sManager->mQueue.Length()" " (" "Insertion index outside bounds" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertionIndex <= sManager->mQueue.Length()" ") (" "Insertion index outside bounds" ")"); do { *((volatile int*)__null) = 346; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
347 | sManager->mQueue.InsertElementAt(insertionIndex, std::move(newdata)); |
348 | } |
349 | |
350 | if (hostFound) { |
351 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to " "CONNECTING_QUEUED"); } } while (0) |
352 | ("Websocket: some other channel is connecting, changing state to "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to " "CONNECTING_QUEUED"); } } while (0) |
353 | "CONNECTING_QUEUED"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: some other channel is connecting, changing state to " "CONNECTING_QUEUED"); } } while (0); |
354 | ws->mConnecting = CONNECTING_QUEUED; |
355 | } else { |
356 | sManager->mFailures.DelayOrBegin(ws); |
357 | } |
358 | } |
359 | |
360 | static void OnConnected(WebSocketChannel* aChannel) { |
361 | LOG(("Websocket: OnConnected: [this=%p]", aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnConnected: [this=%p]" , aChannel); } } while (0); |
362 | |
363 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 363; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
364 | MOZ_ASSERT(aChannel->mConnecting == CONNECTING_IN_PROGRESS,do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChannel->mConnecting == CONNECTING_IN_PROGRESS)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aChannel->mConnecting == CONNECTING_IN_PROGRESS)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChannel->mConnecting == CONNECTING_IN_PROGRESS" " (" "Channel completed connect, but not connecting?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS" ") (" "Channel completed connect, but not connecting?" ")"); do { *((volatile int*)__null) = 365; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false) |
365 | "Channel completed connect, but not connecting?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aChannel->mConnecting == CONNECTING_IN_PROGRESS)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aChannel->mConnecting == CONNECTING_IN_PROGRESS)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChannel->mConnecting == CONNECTING_IN_PROGRESS" " (" "Channel completed connect, but not connecting?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel->mConnecting == CONNECTING_IN_PROGRESS" ") (" "Channel completed connect, but not connecting?" ")"); do { *((volatile int*)__null) = 365; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false); |
366 | |
367 | StaticMutexAutoLock lock(sLock); |
368 | if (!sManager) { |
369 | return; |
370 | } |
371 | |
372 | LOG(("Websocket: changing state to NOT_CONNECTING"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to NOT_CONNECTING" ); } } while (0); |
373 | aChannel->mConnecting = NOT_CONNECTING; |
374 | |
375 | // Remove from queue |
376 | sManager->RemoveFromQueue(aChannel); |
377 | |
378 | // Connection succeeded, so stop keeping track of any previous failures |
379 | sManager->mFailures.Remove(aChannel->mAddress, aChannel->mPath, |
380 | aChannel->mPort); |
381 | |
382 | // Check for queued connections to same host. |
383 | // Note: still need to check for failures, since next websocket with same |
384 | // host may have different port |
385 | sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix); |
386 | } |
387 | |
388 | // Called every time a websocket channel ends its session (including going |
389 | // away w/o ever successfully creating a connection) |
390 | static void OnStopSession(WebSocketChannel* aChannel, nsresult aReason) { |
391 | LOG(("Websocket: OnStopSession: [this=%p, reason=0x%08" PRIx32 "]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnStopSession: [this=%p, reason=0x%08" "x" "]", aChannel, static_cast<uint32_t>(aReason)); } } while (0) |
392 | aChannel, static_cast<uint32_t>(aReason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: OnStopSession: [this=%p, reason=0x%08" "x" "]", aChannel, static_cast<uint32_t>(aReason)); } } while (0); |
393 | |
394 | StaticMutexAutoLock lock(sLock); |
395 | if (!sManager) { |
396 | return; |
397 | } |
398 | |
399 | if (NS_FAILED(aReason)((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0)))) { |
400 | // Have we seen this failure before? |
401 | FailDelay* knownFailure = sManager->mFailures.Lookup( |
402 | aChannel->mAddress, aChannel->mPath, aChannel->mPort); |
403 | if (knownFailure) { |
404 | if (aReason == NS_ERROR_NOT_CONNECTED) { |
405 | // Don't count close() before connection as a network error |
406 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
407 | ("Websocket close() before connection to %s, %s, %d completed"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
408 | " [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
409 | aChannel->mAddress.get(), aChannel->mPath.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0) |
410 | (int)aChannel->mPort, aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket close() before connection to %s, %s, %d completed" " [this=%p]", aChannel->mAddress.get(), aChannel->mPath .get(), (int)aChannel->mPort, aChannel); } } while (0); |
411 | } else { |
412 | // repeated failure to connect: increase delay for next connection |
413 | knownFailure->FailedAgain(); |
414 | } |
415 | } else { |
416 | // new connection failure: record it. |
417 | LOG(("WebSocket: connection to %s, %s, %d failed: [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]" , aChannel->mAddress.get(), aChannel->mPath.get(), (int )aChannel->mPort, aChannel); } } while (0) |
418 | aChannel->mAddress.get(), aChannel->mPath.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]" , aChannel->mAddress.get(), aChannel->mPath.get(), (int )aChannel->mPort, aChannel); } } while (0) |
419 | (int)aChannel->mPort, aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: connection to %s, %s, %d failed: [this=%p]" , aChannel->mAddress.get(), aChannel->mPath.get(), (int )aChannel->mPort, aChannel); } } while (0); |
420 | sManager->mFailures.Add(aChannel->mAddress, aChannel->mPath, |
421 | aChannel->mPort); |
422 | } |
423 | } |
424 | |
425 | if (NS_IsMainThread()) { |
426 | ContinueOnStopSession(aChannel, aReason); |
427 | } else { |
428 | NS_DispatchToMainThread(NS_NewRunnableFunction( |
429 | "nsWSAdmissionManager::ContinueOnStopSession", |
430 | [channel = RefPtr{aChannel}, reason = aReason]() { |
431 | StaticMutexAutoLock lock(sLock); |
432 | if (!sManager) { |
433 | return; |
434 | } |
435 | |
436 | nsWSAdmissionManager::ContinueOnStopSession(channel, reason); |
437 | })); |
438 | } |
439 | } |
440 | |
441 | static void ContinueOnStopSession(WebSocketChannel* aChannel, |
442 | nsresult aReason) { |
443 | sLock.AssertCurrentThreadOwns(); |
444 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 444; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
445 | |
446 | if (!aChannel->mConnecting) { |
447 | return; |
448 | } |
449 | |
450 | // Only way a connecting channel may get here w/o failing is if it |
451 | // was closed with GOING_AWAY (1001) because of navigation, tab |
452 | // close, etc. |
453 | #ifdef DEBUG1 |
454 | { |
455 | MutexAutoLock lock(aChannel->mMutex); |
456 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" " (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" ") (" "websocket closed while connecting w/o failing?" ")"); do { *((volatile int*)__null) = 458; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false) |
457 | NS_FAILED(aReason) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY,do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" " (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" ") (" "websocket closed while connecting w/o failing?" ")"); do { *((volatile int*)__null) = 458; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false) |
458 | "websocket closed while connecting w/o failing?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)) , 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" " (" "websocket closed while connecting w/o failing?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aReason)), 0))) || aChannel->mScriptCloseCode == CLOSE_GOING_AWAY" ") (" "websocket closed while connecting w/o failing?" ")"); do { *((volatile int*)__null) = 458; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false); |
459 | } |
460 | #endif |
461 | Unused << aReason; |
462 | |
463 | sManager->RemoveFromQueue(aChannel); |
464 | |
465 | bool wasNotQueued = (aChannel->mConnecting != CONNECTING_QUEUED); |
466 | LOG(("Websocket: changing state to NOT_CONNECTING"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to NOT_CONNECTING" ); } } while (0); |
467 | aChannel->mConnecting = NOT_CONNECTING; |
468 | if (wasNotQueued) { |
469 | sManager->ConnectNext(aChannel->mAddress, aChannel->mOriginSuffix); |
470 | } |
471 | } |
472 | |
473 | static void IncrementSessionCount() { |
474 | StaticMutexAutoLock lock(sLock); |
475 | if (!sManager) { |
476 | return; |
477 | } |
478 | sManager->mSessionCount++; |
479 | } |
480 | |
481 | static void DecrementSessionCount() { |
482 | StaticMutexAutoLock lock(sLock); |
483 | if (!sManager) { |
484 | return; |
485 | } |
486 | sManager->mSessionCount--; |
487 | } |
488 | |
489 | static void GetSessionCount(int32_t& aSessionCount) { |
490 | StaticMutexAutoLock lock(sLock); |
491 | if (!sManager) { |
492 | return; |
493 | } |
494 | aSessionCount = sManager->mSessionCount; |
495 | } |
496 | |
497 | private: |
498 | nsWSAdmissionManager() : mSessionCount(0) { |
499 | MOZ_COUNT_CTOR(nsWSAdmissionManager)do { static_assert(std::is_class_v<nsWSAdmissionManager> , "Token '" "nsWSAdmissionManager" "' is not a class type."); static_assert(!std::is_base_of<nsISupports, nsWSAdmissionManager >::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsWSAdmissionManager" , sizeof(*this)); } while (0); |
500 | } |
501 | |
502 | ~nsWSAdmissionManager() { MOZ_COUNT_DTOR(nsWSAdmissionManager)do { static_assert(std::is_class_v<nsWSAdmissionManager> , "Token '" "nsWSAdmissionManager" "' is not a class type."); static_assert(!std::is_base_of<nsISupports, nsWSAdmissionManager >::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsWSAdmissionManager" , sizeof(*this)); } while (0); } |
503 | |
504 | class nsOpenConn { |
505 | public: |
506 | nsOpenConn(nsCString& addr, nsCString& originSuffix, bool failed, |
507 | WebSocketChannel* channel) |
508 | : mAddress(addr), |
509 | mOriginSuffix(originSuffix), |
510 | mFailed(failed), |
511 | mChannel(channel) { |
512 | MOZ_COUNT_CTOR(nsOpenConn)do { static_assert(std::is_class_v<nsOpenConn>, "Token '" "nsOpenConn" "' is not a class type."); static_assert(!std:: is_base_of<nsISupports, nsOpenConn>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsOpenConn", sizeof (*this)); } while (0); |
513 | } |
514 | MOZ_COUNTED_DTOR(nsOpenConn)~nsOpenConn() { do { static_assert(std::is_class_v<nsOpenConn >, "Token '" "nsOpenConn" "' is not a class type."); static_assert (!std::is_base_of<nsISupports, nsOpenConn>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsOpenConn", sizeof (*this)); } while (0); } |
515 | |
516 | nsCString mAddress; |
517 | nsCString mOriginSuffix; |
518 | bool mFailed = false; |
519 | RefPtr<WebSocketChannel> mChannel; |
520 | }; |
521 | |
522 | void ConnectNext(nsCString& hostName, nsCString& originSuffix) { |
523 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 523; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
524 | |
525 | int32_t index = IndexOf(hostName, originSuffix); |
526 | if (index >= 0) { |
527 | WebSocketChannel* chan = mQueue[index]->mChannel; |
528 | |
529 | MOZ_ASSERT(chan->mConnecting == CONNECTING_QUEUED,do { static_assert( mozilla::detail::AssertionConditionType< decltype(chan->mConnecting == CONNECTING_QUEUED)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(chan->mConnecting == CONNECTING_QUEUED))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("chan->mConnecting == CONNECTING_QUEUED" " (" "transaction not queued but in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED" ") (" "transaction not queued but in queue" ")"); do { *((volatile int*)__null) = 530; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
530 | "transaction not queued but in queue")do { static_assert( mozilla::detail::AssertionConditionType< decltype(chan->mConnecting == CONNECTING_QUEUED)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(chan->mConnecting == CONNECTING_QUEUED))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("chan->mConnecting == CONNECTING_QUEUED" " (" "transaction not queued but in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "chan->mConnecting == CONNECTING_QUEUED" ") (" "transaction not queued but in queue" ")"); do { *((volatile int*)__null) = 530; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
531 | LOG(("WebSocket: ConnectNext: found channel [this=%p] in queue", chan))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: ConnectNext: found channel [this=%p] in queue" , chan); } } while (0); |
532 | |
533 | mFailures.DelayOrBegin(chan); |
534 | } |
535 | } |
536 | |
537 | void RemoveFromQueue(WebSocketChannel* aChannel) { |
538 | LOG(("Websocket: RemoveFromQueue: [this=%p]", aChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: RemoveFromQueue: [this=%p]" , aChannel); } } while (0); |
539 | int32_t index = IndexOf(aChannel); |
540 | MOZ_ASSERT(index >= 0, "connection to remove not in queue")do { static_assert( mozilla::detail::AssertionConditionType< decltype(index >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(index >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("index >= 0" " (" "connection to remove not in queue" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index >= 0" ") (" "connection to remove not in queue" ")"); do { *((volatile int*)__null) = 540; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
541 | if (index >= 0) { |
542 | mQueue.RemoveElementAt(index); |
543 | } |
544 | } |
545 | |
546 | int32_t IndexOf(nsCString& aAddress, nsCString& aOriginSuffix) { |
547 | for (uint32_t i = 0; i < mQueue.Length(); i++) { |
548 | bool isPartitioned = StaticPrefs::privacy_partition_network_state() || |
549 | StaticPrefs::privacy_firstparty_isolate(); |
550 | if (aAddress == (mQueue[i])->mAddress && |
551 | (!isPartitioned || aOriginSuffix == (mQueue[i])->mOriginSuffix)) { |
552 | return i; |
553 | } |
554 | } |
555 | return -1; |
556 | } |
557 | |
558 | int32_t IndexOf(WebSocketChannel* aChannel) { |
559 | for (uint32_t i = 0; i < mQueue.Length(); i++) { |
560 | if (aChannel == (mQueue[i])->mChannel) return i; |
561 | } |
562 | return -1; |
563 | } |
564 | |
565 | // Returns the index of the first entry that failed, or else the last entry if |
566 | // none found |
567 | uint32_t IndexOfFirstFailure() { |
568 | for (uint32_t i = 0; i < mQueue.Length(); i++) { |
569 | if (mQueue[i]->mFailed) return i; |
570 | } |
571 | return mQueue.Length(); |
572 | } |
573 | |
574 | // SessionCount might be decremented from the main or the socket |
575 | // thread, so manage it with atomic counters |
576 | Atomic<int32_t> mSessionCount; |
577 | |
578 | // Queue for websockets that have not completed connecting yet. |
579 | // The first nsOpenConn with a given address will be either be |
580 | // CONNECTING_IN_PROGRESS or CONNECTING_DELAYED. Later ones with the same |
581 | // hostname must be CONNECTING_QUEUED. |
582 | // |
583 | // We could hash hostnames instead of using a single big vector here, but the |
584 | // dataset is expected to be small. |
585 | nsTArray<UniquePtr<nsOpenConn>> mQueue; |
586 | |
587 | FailDelayManager mFailures; |
588 | |
589 | static nsWSAdmissionManager* sManager MOZ_GUARDED_BY(sLock)__attribute__((guarded_by(sLock))); |
590 | static StaticMutex sLock; |
591 | }; |
592 | |
593 | nsWSAdmissionManager* nsWSAdmissionManager::sManager; |
594 | StaticMutex nsWSAdmissionManager::sLock; |
595 | |
596 | //----------------------------------------------------------------------------- |
597 | // CallOnMessageAvailable |
598 | //----------------------------------------------------------------------------- |
599 | |
600 | class CallOnMessageAvailable final : public Runnable { |
601 | public: |
602 | CallOnMessageAvailable(WebSocketChannel* aChannel, nsACString& aData, |
603 | int32_t aLen) |
604 | : Runnable("net::CallOnMessageAvailable"), |
605 | mChannel(aChannel), |
606 | mListenerMT(aChannel->mListenerMT), |
607 | mData(aData), |
608 | mLen(aLen) {} |
609 | |
610 | NS_IMETHODvirtual nsresult Run() override { |
611 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 611; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
612 | |
613 | if (mListenerMT) { |
614 | nsresult rv; |
615 | if (mLen < 0) { |
616 | rv = mListenerMT->mListener->OnMessageAvailable(mListenerMT->mContext, |
617 | mData); |
618 | } else { |
619 | rv = mListenerMT->mListener->OnBinaryMessageAvailable( |
620 | mListenerMT->mContext, mData); |
621 | } |
622 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
623 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
624 | ("OnMessageAvailable or OnBinaryMessageAvailable "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
625 | "failed with 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
626 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "OnMessageAvailable or OnBinaryMessageAvailable " "failed with 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0); |
627 | } |
628 | } |
629 | |
630 | return NS_OK; |
631 | } |
632 | |
633 | private: |
634 | ~CallOnMessageAvailable() = default; |
635 | |
636 | RefPtr<WebSocketChannel> mChannel; |
637 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
638 | nsCString mData; |
639 | int32_t mLen; |
640 | }; |
641 | |
642 | //----------------------------------------------------------------------------- |
643 | // CallOnStop |
644 | //----------------------------------------------------------------------------- |
645 | |
646 | class CallOnStop final : public Runnable { |
647 | public: |
648 | CallOnStop(WebSocketChannel* aChannel, nsresult aReason) |
649 | : Runnable("net::CallOnStop"), |
650 | mChannel(aChannel), |
651 | mListenerMT(mChannel->mListenerMT), |
652 | mReason(aReason) {} |
653 | |
654 | NS_IMETHODvirtual nsresult Run() override { |
655 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 655; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
656 | |
657 | if (mListenerMT) { |
658 | nsresult rv = |
659 | mListenerMT->mListener->OnStop(mListenerMT->mContext, mReason); |
660 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
661 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0) |
662 | ("WebSocketChannel::CallOnStop "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0) |
663 | "OnStop failed (%08" PRIx32 ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0) |
664 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnStop " "OnStop failed (%08" "x" ")\n", static_cast<uint32_t>( rv)); } } while (0); |
665 | } |
666 | mChannel->mListenerMT = nullptr; |
667 | } |
668 | |
669 | return NS_OK; |
670 | } |
671 | |
672 | private: |
673 | ~CallOnStop() = default; |
674 | |
675 | RefPtr<WebSocketChannel> mChannel; |
676 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
677 | nsresult mReason; |
678 | }; |
679 | |
680 | //----------------------------------------------------------------------------- |
681 | // CallOnServerClose |
682 | //----------------------------------------------------------------------------- |
683 | |
684 | class CallOnServerClose final : public Runnable { |
685 | public: |
686 | CallOnServerClose(WebSocketChannel* aChannel, uint16_t aCode, |
687 | nsACString& aReason) |
688 | : Runnable("net::CallOnServerClose"), |
689 | mChannel(aChannel), |
690 | mListenerMT(mChannel->mListenerMT), |
691 | mCode(aCode), |
692 | mReason(aReason) {} |
693 | |
694 | NS_IMETHODvirtual nsresult Run() override { |
695 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 695; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
696 | |
697 | if (mListenerMT) { |
698 | nsresult rv = mListenerMT->mListener->OnServerClose(mListenerMT->mContext, |
699 | mCode, mReason); |
700 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
701 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0) |
702 | ("WebSocketChannel::CallOnServerClose "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0) |
703 | "OnServerClose failed (%08" PRIx32 ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0) |
704 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnServerClose " "OnServerClose failed (%08" "x" ")\n", static_cast<uint32_t >(rv)); } } while (0); |
705 | } |
706 | } |
707 | return NS_OK; |
708 | } |
709 | |
710 | private: |
711 | ~CallOnServerClose() = default; |
712 | |
713 | RefPtr<WebSocketChannel> mChannel; |
714 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
715 | uint16_t mCode; |
716 | nsCString mReason; |
717 | }; |
718 | |
719 | //----------------------------------------------------------------------------- |
720 | // CallAcknowledge |
721 | //----------------------------------------------------------------------------- |
722 | |
723 | class CallAcknowledge final : public Runnable { |
724 | public: |
725 | CallAcknowledge(WebSocketChannel* aChannel, uint32_t aSize) |
726 | : Runnable("net::CallAcknowledge"), |
727 | mChannel(aChannel), |
728 | mListenerMT(mChannel->mListenerMT), |
729 | mSize(aSize) {} |
730 | |
731 | NS_IMETHODvirtual nsresult Run() override { |
732 | MOZ_ASSERT(mChannel->IsOnTargetThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChannel->IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChannel->IsOnTargetThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mChannel->IsOnTargetThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChannel->IsOnTargetThread()" ")"); do { *((volatile int*)__null) = 732; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
733 | |
734 | LOG(("WebSocketChannel::CallAcknowledge: Size %u\n", mSize))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Size %u\n" , mSize); } } while (0); |
735 | if (mListenerMT) { |
736 | nsresult rv = |
737 | mListenerMT->mListener->OnAcknowledge(mListenerMT->mContext, mSize); |
738 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
739 | LOG(("WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" "x" ")\n", static_cast<uint32_t>(rv)); } } while (0) |
740 | ")\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" "x" ")\n", static_cast<uint32_t>(rv)); } } while (0) |
741 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallAcknowledge: Acknowledge failed (%08" "x" ")\n", static_cast<uint32_t>(rv)); } } while (0); |
742 | } |
743 | } |
744 | return NS_OK; |
745 | } |
746 | |
747 | private: |
748 | ~CallAcknowledge() = default; |
749 | |
750 | RefPtr<WebSocketChannel> mChannel; |
751 | RefPtr<BaseWebSocketChannel::ListenerAndContextContainer> mListenerMT; |
752 | uint32_t mSize; |
753 | }; |
754 | |
755 | //----------------------------------------------------------------------------- |
756 | // CallOnTransportAvailable |
757 | //----------------------------------------------------------------------------- |
758 | |
759 | class CallOnTransportAvailable final : public Runnable { |
760 | public: |
761 | CallOnTransportAvailable(WebSocketChannel* aChannel, |
762 | nsISocketTransport* aTransport, |
763 | nsIAsyncInputStream* aSocketIn, |
764 | nsIAsyncOutputStream* aSocketOut) |
765 | : Runnable("net::CallOnTransportAvailble"), |
766 | mChannel(aChannel), |
767 | mTransport(aTransport), |
768 | mSocketIn(aSocketIn), |
769 | mSocketOut(aSocketOut) {} |
770 | |
771 | NS_IMETHODvirtual nsresult Run() override { |
772 | LOG(("WebSocketChannel::CallOnTransportAvailable %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallOnTransportAvailable %p\n" , this); } } while (0); |
773 | return mChannel->OnTransportAvailable(mTransport, mSocketIn, mSocketOut); |
774 | } |
775 | |
776 | private: |
777 | ~CallOnTransportAvailable() = default; |
778 | |
779 | RefPtr<WebSocketChannel> mChannel; |
780 | nsCOMPtr<nsISocketTransport> mTransport; |
781 | nsCOMPtr<nsIAsyncInputStream> mSocketIn; |
782 | nsCOMPtr<nsIAsyncOutputStream> mSocketOut; |
783 | }; |
784 | |
785 | //----------------------------------------------------------------------------- |
786 | // PMCECompression |
787 | //----------------------------------------------------------------------------- |
788 | |
789 | class PMCECompression { |
790 | public: |
791 | PMCECompression(bool aNoContextTakeover, int32_t aLocalMaxWindowBits, |
792 | int32_t aRemoteMaxWindowBits) |
793 | : mActive(false), |
794 | mNoContextTakeover(aNoContextTakeover), |
795 | mResetDeflater(false), |
796 | mMessageDeflated(false) { |
797 | this->mDeflater.next_in = nullptr; |
798 | this->mDeflater.avail_in = 0; |
799 | this->mDeflater.total_in = 0; |
800 | this->mDeflater.next_out = nullptr; |
801 | this->mDeflater.avail_out = 0; |
802 | this->mDeflater.total_out = 0; |
803 | this->mDeflater.msg = nullptr; |
804 | this->mDeflater.state = nullptr; |
805 | this->mDeflater.data_type = 0; |
806 | this->mDeflater.adler = 0; |
807 | this->mDeflater.reserved = 0; |
808 | this->mInflater.next_in = nullptr; |
809 | this->mInflater.avail_in = 0; |
810 | this->mInflater.total_in = 0; |
811 | this->mInflater.next_out = nullptr; |
812 | this->mInflater.avail_out = 0; |
813 | this->mInflater.total_out = 0; |
814 | this->mInflater.msg = nullptr; |
815 | this->mInflater.state = nullptr; |
816 | this->mInflater.data_type = 0; |
817 | this->mInflater.adler = 0; |
818 | this->mInflater.reserved = 0; |
819 | MOZ_COUNT_CTOR(PMCECompression)do { static_assert(std::is_class_v<PMCECompression>, "Token '" "PMCECompression" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, PMCECompression>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "PMCECompression" , sizeof(*this)); } while (0); |
820 | |
821 | mDeflater.zalloc = mInflater.zalloc = Z_NULL0; |
822 | mDeflater.zfree = mInflater.zfree = Z_NULL0; |
823 | mDeflater.opaque = mInflater.opaque = Z_NULL0; |
824 | |
825 | if (deflateInit2(&mDeflater, Z_DEFAULT_COMPRESSION, Z_DEFLATED,MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits ),(8), (0), "1.3.1", (int)sizeof(z_stream)) |
826 | -aLocalMaxWindowBits, 8, Z_DEFAULT_STRATEGY)MOZ_Z_deflateInit2_((&mDeflater),((-1)),(8),(-aLocalMaxWindowBits ),(8), (0), "1.3.1", (int)sizeof(z_stream)) == Z_OK0) { |
827 | if (inflateInit2(&mInflater, -aRemoteMaxWindowBits)MOZ_Z_inflateInit2_((&mInflater), (-aRemoteMaxWindowBits) , "1.3.1", (int)sizeof(z_stream)) == Z_OK0) { |
828 | mActive = true; |
829 | } else { |
830 | deflateEndMOZ_Z_deflateEnd(&mDeflater); |
831 | } |
832 | } |
833 | } |
834 | |
835 | ~PMCECompression() { |
836 | MOZ_COUNT_DTOR(PMCECompression)do { static_assert(std::is_class_v<PMCECompression>, "Token '" "PMCECompression" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, PMCECompression>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "PMCECompression" , sizeof(*this)); } while (0); |
837 | |
838 | if (mActive) { |
839 | inflateEndMOZ_Z_inflateEnd(&mInflater); |
840 | deflateEndMOZ_Z_deflateEnd(&mDeflater); |
841 | } |
842 | } |
843 | |
844 | bool Active() { return mActive; } |
845 | |
846 | void SetMessageDeflated() { |
847 | MOZ_ASSERT(!mMessageDeflated)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mMessageDeflated)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mMessageDeflated))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mMessageDeflated" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mMessageDeflated" ")"); do { *((volatile int*)__null) = 847; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
848 | mMessageDeflated = true; |
849 | } |
850 | bool IsMessageDeflated() { return mMessageDeflated; } |
851 | |
852 | bool UsingContextTakeover() { return !mNoContextTakeover; } |
853 | |
854 | nsresult Deflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) { |
855 | if (mResetDeflater || mNoContextTakeover) { |
856 | if (deflateResetMOZ_Z_deflateReset(&mDeflater) != Z_OK0) { |
857 | return NS_ERROR_UNEXPECTED; |
858 | } |
859 | mResetDeflater = false; |
860 | } |
861 | |
862 | mDeflater.avail_out = kBufferLen; |
863 | mDeflater.next_out = mBuffer; |
864 | mDeflater.avail_in = dataLen; |
865 | mDeflater.next_in = data; |
866 | |
867 | while (true) { |
868 | int zerr = deflateMOZ_Z_deflate(&mDeflater, Z_SYNC_FLUSH2); |
869 | |
870 | if (zerr != Z_OK0) { |
871 | mResetDeflater = true; |
872 | return NS_ERROR_UNEXPECTED; |
873 | } |
874 | |
875 | uint32_t deflated = kBufferLen - mDeflater.avail_out; |
876 | if (deflated > 0) { |
877 | _retval.Append(reinterpret_cast<char*>(mBuffer), deflated); |
878 | } |
879 | |
880 | mDeflater.avail_out = kBufferLen; |
881 | mDeflater.next_out = mBuffer; |
882 | |
883 | if (mDeflater.avail_in > 0) { |
884 | continue; // There is still some data to deflate |
885 | } |
886 | |
887 | if (deflated == kBufferLen) { |
888 | continue; // There was not enough space in the buffer |
889 | } |
890 | |
891 | break; |
892 | } |
893 | |
894 | if (_retval.Length() < 4) { |
895 | MOZ_ASSERT(false, "Expected trailing not found in deflated data!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Expected trailing not found in deflated data!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Expected trailing not found in deflated data!" ")"); do { * ((volatile int*)__null) = 895; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
896 | mResetDeflater = true; |
897 | return NS_ERROR_UNEXPECTED; |
898 | } |
899 | |
900 | _retval.Truncate(_retval.Length() - 4); |
901 | |
902 | return NS_OK; |
903 | } |
904 | |
905 | nsresult Inflate(uint8_t* data, uint32_t dataLen, nsACString& _retval) { |
906 | mMessageDeflated = false; |
907 | |
908 | Bytef trailingData[] = {0x00, 0x00, 0xFF, 0xFF}; |
909 | bool trailingDataUsed = false; |
910 | |
911 | mInflater.avail_out = kBufferLen; |
912 | mInflater.next_out = mBuffer; |
913 | mInflater.avail_in = dataLen; |
914 | mInflater.next_in = data; |
915 | |
916 | while (true) { |
917 | int zerr = inflateMOZ_Z_inflate(&mInflater, Z_NO_FLUSH0); |
918 | |
919 | if (zerr == Z_STREAM_END1) { |
920 | Bytef* saveNextIn = mInflater.next_in; |
921 | uint32_t saveAvailIn = mInflater.avail_in; |
922 | Bytef* saveNextOut = mInflater.next_out; |
923 | uint32_t saveAvailOut = mInflater.avail_out; |
924 | |
925 | inflateResetMOZ_Z_inflateReset(&mInflater); |
926 | |
927 | mInflater.next_in = saveNextIn; |
928 | mInflater.avail_in = saveAvailIn; |
929 | mInflater.next_out = saveNextOut; |
930 | mInflater.avail_out = saveAvailOut; |
931 | } else if (zerr != Z_OK0 && zerr != Z_BUF_ERROR(-5)) { |
932 | return NS_ERROR_INVALID_CONTENT_ENCODING; |
933 | } |
934 | |
935 | uint32_t inflated = kBufferLen - mInflater.avail_out; |
936 | if (inflated > 0) { |
937 | if (!_retval.Append(reinterpret_cast<char*>(mBuffer), inflated, |
938 | fallible)) { |
939 | return NS_ERROR_OUT_OF_MEMORY; |
940 | } |
941 | } |
942 | |
943 | mInflater.avail_out = kBufferLen; |
944 | mInflater.next_out = mBuffer; |
945 | |
946 | if (mInflater.avail_in > 0) { |
947 | continue; // There is still some data to inflate |
948 | } |
949 | |
950 | if (inflated == kBufferLen) { |
951 | continue; // There was not enough space in the buffer |
952 | } |
953 | |
954 | if (!trailingDataUsed) { |
955 | trailingDataUsed = true; |
956 | mInflater.avail_in = sizeof(trailingData); |
957 | mInflater.next_in = trailingData; |
958 | continue; |
959 | } |
960 | |
961 | return NS_OK; |
962 | } |
963 | } |
964 | |
965 | private: |
966 | bool mActive; |
967 | bool mNoContextTakeover; |
968 | bool mResetDeflater; |
969 | bool mMessageDeflated; |
970 | z_stream mDeflater{}; |
971 | z_stream mInflater{}; |
972 | const static uint32_t kBufferLen = 4096; |
973 | uint8_t mBuffer[kBufferLen]{0}; |
974 | }; |
975 | |
976 | //----------------------------------------------------------------------------- |
977 | // OutboundMessage |
978 | //----------------------------------------------------------------------------- |
979 | |
980 | enum WsMsgType { |
981 | kMsgTypeString = 0, |
982 | kMsgTypeBinaryString, |
983 | kMsgTypeStream, |
984 | kMsgTypePing, |
985 | kMsgTypePong, |
986 | kMsgTypeFin |
987 | }; |
988 | |
989 | static const char* msgNames[] = {"text", "binaryString", "binaryStream", |
990 | "ping", "pong", "close"}; |
991 | |
992 | class OutboundMessage { |
993 | public: |
994 | OutboundMessage(WsMsgType type, const nsACString& str) |
995 | : mMsg(mozilla::AsVariant(pString(str))), |
996 | mMsgType(type), |
997 | mDeflated(false) { |
998 | MOZ_COUNT_CTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '" "OutboundMessage" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "OutboundMessage" , sizeof(*this)); } while (0); |
999 | } |
1000 | |
1001 | OutboundMessage(nsIInputStream* stream, uint32_t length) |
1002 | : mMsg(mozilla::AsVariant(StreamWithLength(stream, length))), |
1003 | mMsgType(kMsgTypeStream), |
1004 | mDeflated(false) { |
1005 | MOZ_COUNT_CTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '" "OutboundMessage" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "OutboundMessage" , sizeof(*this)); } while (0); |
1006 | } |
1007 | |
1008 | ~OutboundMessage() { |
1009 | MOZ_COUNT_DTOR(OutboundMessage)do { static_assert(std::is_class_v<OutboundMessage>, "Token '" "OutboundMessage" "' is not a class type."); static_assert(! std::is_base_of<nsISupports, OutboundMessage>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "OutboundMessage" , sizeof(*this)); } while (0); |
1010 | switch (mMsgType) { |
1011 | case kMsgTypeString: |
1012 | case kMsgTypeBinaryString: |
1013 | case kMsgTypePing: |
1014 | case kMsgTypePong: |
1015 | break; |
1016 | case kMsgTypeStream: |
1017 | // for now this only gets hit if msg deleted w/o being sent |
1018 | if (mMsg.as<StreamWithLength>().mStream) { |
1019 | mMsg.as<StreamWithLength>().mStream->Close(); |
1020 | } |
1021 | break; |
1022 | case kMsgTypeFin: |
1023 | break; // do-nothing: avoid compiler warning |
1024 | } |
1025 | } |
1026 | |
1027 | WsMsgType GetMsgType() const { return mMsgType; } |
1028 | int32_t Length() { |
1029 | if (mMsg.is<pString>()) { |
1030 | return mMsg.as<pString>().mValue.Length(); |
1031 | } |
1032 | |
1033 | return mMsg.as<StreamWithLength>().mLength; |
1034 | } |
1035 | int32_t OrigLength() { |
1036 | if (mMsg.is<pString>()) { |
1037 | pString& ref = mMsg.as<pString>(); |
1038 | return mDeflated ? ref.mOrigValue.Length() : ref.mValue.Length(); |
1039 | } |
1040 | |
1041 | return mMsg.as<StreamWithLength>().mLength; |
1042 | } |
1043 | |
1044 | uint8_t* BeginWriting() { |
1045 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1046; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1046 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1046; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1047 | if (!mMsg.as<pString>().mValue.IsVoid()) { |
1048 | return (uint8_t*)mMsg.as<pString>().mValue.BeginWriting(); |
1049 | } |
1050 | return nullptr; |
1051 | } |
1052 | |
1053 | uint8_t* BeginReading() { |
1054 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1055; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1055 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1055; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1056 | if (!mMsg.as<pString>().mValue.IsVoid()) { |
1057 | return (uint8_t*)mMsg.as<pString>().mValue.BeginReading(); |
1058 | } |
1059 | return nullptr; |
1060 | } |
1061 | |
1062 | uint8_t* BeginOrigReading() { |
1063 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1064; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1064 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1064; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1065 | if (!mDeflated) return BeginReading(); |
1066 | if (!mMsg.as<pString>().mOrigValue.IsVoid()) { |
1067 | return (uint8_t*)mMsg.as<pString>().mOrigValue.BeginReading(); |
1068 | } |
1069 | return nullptr; |
1070 | } |
1071 | |
1072 | nsresult ConvertStreamToString() { |
1073 | MOZ_ASSERT(mMsgType == kMsgTypeStream, "Not a stream!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType == kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType == kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType == kMsgTypeStream" " (" "Not a stream!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType == kMsgTypeStream" ") (" "Not a stream!" ")"); do { *((volatile int*)__null) = 1073 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1074 | nsAutoCString temp; |
1075 | { |
1076 | StreamWithLength& ref = mMsg.as<StreamWithLength>(); |
1077 | nsresult rv = NS_ReadInputStreamToString(ref.mStream, temp, ref.mLength); |
1078 | |
1079 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1079); return rv; } } while (false); |
1080 | if (temp.Length() != ref.mLength) { |
1081 | return NS_ERROR_UNEXPECTED; |
1082 | } |
1083 | ref.mStream->Close(); |
1084 | } |
1085 | |
1086 | mMsg = mozilla::AsVariant(pString(temp)); |
1087 | mMsgType = kMsgTypeBinaryString; |
1088 | |
1089 | return NS_OK; |
1090 | } |
1091 | |
1092 | bool DeflatePayload(PMCECompression* aCompressor) { |
1093 | MOZ_ASSERT(mMsgType != kMsgTypeStream,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1094; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1094 | "Stream should have been converted to string by now")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMsgType != kMsgTypeStream)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMsgType != kMsgTypeStream)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mMsgType != kMsgTypeStream" " (" "Stream should have been converted to string by now" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMsgType != kMsgTypeStream" ") (" "Stream should have been converted to string by now" ")" ); do { *((volatile int*)__null) = 1094; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1095 | MOZ_ASSERT(!mDeflated)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeflated)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeflated))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeflated", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDeflated" ")"); do { *((volatile int*)__null) = 1095; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1096 | |
1097 | nsresult rv; |
1098 | pString& ref = mMsg.as<pString>(); |
1099 | if (ref.mValue.Length() == 0) { |
1100 | // Empty message |
1101 | return false; |
1102 | } |
1103 | |
1104 | nsAutoCString temp; |
1105 | rv = aCompressor->Deflate(BeginReading(), ref.mValue.Length(), temp); |
1106 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1107 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0) |
1108 | ("WebSocketChannel::OutboundMessage: Deflating payload failed "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0) |
1109 | "[rv=0x%08" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0) |
1110 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Deflating payload failed " "[rv=0x%08" "x" "]\n", static_cast<uint32_t>(rv)); } } while (0); |
1111 | return false; |
1112 | } |
1113 | |
1114 | if (!aCompressor->UsingContextTakeover() && |
1115 | temp.Length() > ref.mValue.Length()) { |
1116 | // When "<local>_no_context_takeover" was negotiated, do not send deflated |
1117 | // payload if it's larger that the original one. OTOH, it makes sense |
1118 | // to send the larger deflated payload when the sliding window is not |
1119 | // reset between messages because if we would skip some deflated block |
1120 | // we would need to empty the sliding window which could affect the |
1121 | // compression of the subsequent messages. |
1122 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1123 | ("WebSocketChannel::OutboundMessage: Not deflating message since the "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1124 | "deflated payload is larger than the original one [deflated=%zd, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1125 | "original=%zd]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0) |
1126 | temp.Length(), ref.mValue.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OutboundMessage: Not deflating message since the " "deflated payload is larger than the original one [deflated=%zd, " "original=%zd]", temp.Length(), ref.mValue.Length()); } } while (0); |
1127 | return false; |
1128 | } |
1129 | |
1130 | mDeflated = true; |
1131 | mMsg.as<pString>().mOrigValue = mMsg.as<pString>().mValue; |
1132 | mMsg.as<pString>().mValue = temp; |
1133 | return true; |
1134 | } |
1135 | |
1136 | private: |
1137 | struct pString { |
1138 | nsCString mValue; |
1139 | nsCString mOrigValue; |
1140 | explicit pString(const nsACString& value) |
1141 | : mValue(value), mOrigValue(VoidCString()) {} |
1142 | }; |
1143 | struct StreamWithLength { |
1144 | nsCOMPtr<nsIInputStream> mStream; |
1145 | uint32_t mLength; |
1146 | explicit StreamWithLength(nsIInputStream* stream, uint32_t Length) |
1147 | : mStream(stream), mLength(Length) {} |
1148 | }; |
1149 | mozilla::Variant<pString, StreamWithLength> mMsg; |
1150 | WsMsgType mMsgType; |
1151 | bool mDeflated; |
1152 | }; |
1153 | |
1154 | //----------------------------------------------------------------------------- |
1155 | // OutboundEnqueuer |
1156 | //----------------------------------------------------------------------------- |
1157 | |
1158 | class OutboundEnqueuer final : public Runnable { |
1159 | public: |
1160 | OutboundEnqueuer(WebSocketChannel* aChannel, OutboundMessage* aMsg) |
1161 | : Runnable("OutboundEnquerer"), mChannel(aChannel), mMessage(aMsg) {} |
1162 | |
1163 | NS_IMETHODvirtual nsresult Run() override { |
1164 | mChannel->EnqueueOutgoingMessage(mChannel->mOutgoingMessages, mMessage); |
1165 | return NS_OK; |
1166 | } |
1167 | |
1168 | private: |
1169 | ~OutboundEnqueuer() = default; |
1170 | |
1171 | RefPtr<WebSocketChannel> mChannel; |
1172 | OutboundMessage* mMessage; |
1173 | }; |
1174 | |
1175 | //----------------------------------------------------------------------------- |
1176 | // WebSocketChannel |
1177 | //----------------------------------------------------------------------------- |
1178 | |
1179 | WebSocketChannel::WebSocketChannel() |
1180 | : mPort(0), |
1181 | mCloseTimeout(20000), |
1182 | mOpenTimeout(20000), |
1183 | mConnecting(NOT_CONNECTING), |
1184 | mMaxConcurrentConnections(200), |
1185 | mInnerWindowID(0), |
1186 | mGotUpgradeOK(0), |
1187 | mRecvdHttpUpgradeTransport(0), |
1188 | mPingOutstanding(0), |
1189 | mReleaseOnTransmit(0), |
1190 | mDataStarted(false), |
1191 | mRequestedClose(false), |
1192 | mClientClosed(false), |
1193 | mServerClosed(false), |
1194 | mStopped(false), |
1195 | mCalledOnStop(false), |
1196 | mTCPClosed(false), |
1197 | mOpenedHttpChannel(false), |
1198 | mIncrementedSessionCount(false), |
1199 | mDecrementedSessionCount(false), |
1200 | mMaxMessageSize(INT32_MAX(2147483647)), |
1201 | mStopOnClose(NS_OK), |
1202 | mServerCloseCode(CLOSE_ABNORMAL), |
1203 | mScriptCloseCode(0), |
1204 | mFragmentOpcode(nsIWebSocketFrame::OPCODE_CONTINUATION), |
1205 | mFragmentAccumulator(0), |
1206 | mBuffered(0), |
1207 | mBufferSize(kIncomingBufferInitialSize), |
1208 | mCurrentOut(nullptr), |
1209 | mCurrentOutSent(0), |
1210 | mHdrOutToSend(0), |
1211 | mHdrOut(nullptr), |
1212 | mCompressorMutex("WebSocketChannel::mCompressorMutex"), |
1213 | mDynamicOutputSize(0), |
1214 | mDynamicOutput(nullptr), |
1215 | mPrivateBrowsing(false), |
1216 | mConnectionLogService(nullptr), |
1217 | mMutex("WebSocketChannel::mMutex") { |
1218 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1218; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1219 | |
1220 | LOG(("WebSocketChannel::WebSocketChannel() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::WebSocketChannel() %p\n" , this); } } while (0); |
1221 | |
1222 | nsWSAdmissionManager::Init(); |
1223 | |
1224 | mFramePtr = mBuffer = static_cast<uint8_t*>(moz_xmalloc(mBufferSize)); |
1225 | |
1226 | nsresult rv; |
1227 | mConnectionLogService = mozilla::components::Dashboard::Service(&rv); |
1228 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) LOG(("Failed to initiate dashboard service."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Failed to initiate dashboard service." ); } } while (0); |
1229 | |
1230 | mService = WebSocketEventService::GetOrCreate(); |
1231 | } |
1232 | |
1233 | WebSocketChannel::~WebSocketChannel() { |
1234 | LOG(("WebSocketChannel::~WebSocketChannel() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::~WebSocketChannel() %p\n" , this); } } while (0); |
1235 | |
1236 | if (mWasOpened) { |
1237 | MOZ_ASSERT(mCalledOnStop, "WebSocket was opened but OnStop was not called")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCalledOnStop)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mCalledOnStop))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCalledOnStop" " (" "WebSocket was opened but OnStop was not called" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCalledOnStop" ") (" "WebSocket was opened but OnStop was not called" ")"); do { *((volatile int*)__null) = 1237; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1238 | MOZ_ASSERT(mStopped, "WebSocket was opened but never stopped")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped" " (" "WebSocket was opened but never stopped" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") (" "WebSocket was opened but never stopped" ")"); do { *((volatile int*)__null) = 1238; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1239 | } |
1240 | MOZ_ASSERT(!mCancelable, "DNS/Proxy Request still alive at destruction")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable" " (" "DNS/Proxy Request still alive at destruction" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ") (" "DNS/Proxy Request still alive at destruction" ")"); do { *((volatile int*)__null) = 1240; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
1241 | MOZ_ASSERT(!mConnecting, "Should not be connecting in destructor")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mConnecting)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mConnecting))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mConnecting" " (" "Should not be connecting in destructor" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnecting" ") (" "Should not be connecting in destructor" ")"); do { *( (volatile int*)__null) = 1241; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
1242 | |
1243 | free(mBuffer); |
1244 | free(mDynamicOutput); |
1245 | delete mCurrentOut; |
1246 | |
1247 | while ((mCurrentOut = mOutgoingPingMessages.PopFront())) { |
1248 | delete mCurrentOut; |
1249 | } |
1250 | while ((mCurrentOut = mOutgoingPongMessages.PopFront())) { |
1251 | delete mCurrentOut; |
1252 | } |
1253 | while ((mCurrentOut = mOutgoingMessages.PopFront())) { |
1254 | delete mCurrentOut; |
1255 | } |
1256 | |
1257 | mListenerMT = nullptr; |
1258 | |
1259 | NS_ReleaseOnMainThread("WebSocketChannel::mService", mService.forget()); |
1260 | } |
1261 | |
1262 | NS_IMETHODIMPnsresult |
1263 | WebSocketChannel::Observe(nsISupports* subject, const char* topic, |
1264 | const char16_t* data) { |
1265 | LOG(("WebSocketChannel::Observe [topic=\"%s\"]\n", topic))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Observe [topic=\"%s\"]\n" , topic); } } while (0); |
1266 | |
1267 | if (strcmp(topic, NS_NETWORK_LINK_TOPIC"network:link-status-changed") == 0) { |
1268 | nsCString converted = NS_ConvertUTF16toUTF8(data); |
1269 | const char* state = converted.get(); |
1270 | |
1271 | if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED"changed") == 0) { |
1272 | LOG(("WebSocket: received network CHANGED event"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: received network CHANGED event" ); } } while (0); |
1273 | |
1274 | if (!mIOThread) { |
1275 | // there has not been an asyncopen yet on the object and then we need |
1276 | // no ping. |
1277 | LOG(("WebSocket: early object, no ping needed"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: early object, no ping needed" ); } } while (0); |
1278 | } else { |
1279 | mIOThread->Dispatch( |
1280 | NewRunnableMethod("net::WebSocketChannel::OnNetworkChanged", this, |
1281 | &WebSocketChannel::OnNetworkChanged), |
1282 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1283 | } |
1284 | } |
1285 | } |
1286 | |
1287 | return NS_OK; |
1288 | } |
1289 | |
1290 | nsresult WebSocketChannel::OnNetworkChanged() { |
1291 | if (!mDataStarted) { |
1292 | LOG(("WebSocket: data not started yet, no ping needed"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: data not started yet, no ping needed" ); } } while (0); |
1293 | return NS_OK; |
1294 | } |
1295 | |
1296 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1296; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1297 | |
1298 | LOG(("WebSocketChannel::OnNetworkChanged() - on socket thread %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnNetworkChanged() - on socket thread %p" , this); } } while (0); |
1299 | |
1300 | if (mPingOutstanding) { |
1301 | // If there's an outstanding ping that's expected to get a pong back |
1302 | // we let that do its thing. |
1303 | LOG(("WebSocket: pong already pending"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: pong already pending" ); } } while (0); |
1304 | return NS_OK; |
1305 | } |
1306 | |
1307 | if (mPingForced) { |
1308 | // avoid more than one |
1309 | LOG(("WebSocket: forced ping timer already fired"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: forced ping timer already fired" ); } } while (0); |
1310 | return NS_OK; |
1311 | } |
1312 | |
1313 | LOG(("nsWebSocketChannel:: Generating Ping as network changed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Generating Ping as network changed\n" ); } } while (0); |
1314 | |
1315 | if (!mPingTimer) { |
1316 | // The ping timer is only conditionally running already. If it wasn't |
1317 | // already created do it here. |
1318 | mPingTimer = NS_NewTimer(); |
1319 | if (!mPingTimer) { |
1320 | LOG(("WebSocket: unable to create ping timer!"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket: unable to create ping timer!" ); } } while (0); |
1321 | NS_WARNING("unable to create ping timer!")NS_DebugBreak(NS_DEBUG_WARNING, "unable to create ping timer!" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1321); |
1322 | return NS_ERROR_OUT_OF_MEMORY; |
1323 | } |
1324 | } |
1325 | // Trigger the ping timeout asap to fire off a new ping. Wait just |
1326 | // a little bit to better avoid multi-triggers. |
1327 | mPingForced = true; |
1328 | mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT); |
1329 | |
1330 | return NS_OK; |
1331 | } |
1332 | |
1333 | void WebSocketChannel::Shutdown() { nsWSAdmissionManager::Shutdown(); } |
1334 | |
1335 | void WebSocketChannel::GetEffectiveURL(nsAString& aEffectiveURL) const { |
1336 | aEffectiveURL = mEffectiveURL; |
1337 | } |
1338 | |
1339 | bool WebSocketChannel::IsEncrypted() const { return mEncrypted; } |
1340 | |
1341 | void WebSocketChannel::BeginOpen(bool aCalledFromAdmissionManager) { |
1342 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1342); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1342; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1343 | |
1344 | LOG(("WebSocketChannel::BeginOpen() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpen() %p\n" , this); } } while (0); |
1345 | |
1346 | // Important that we set CONNECTING_IN_PROGRESS before any call to |
1347 | // AbortSession here: ensures that any remaining queued connection(s) are |
1348 | // scheduled in OnStopSession |
1349 | LOG(("Websocket: changing state to CONNECTING_IN_PROGRESS"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Websocket: changing state to CONNECTING_IN_PROGRESS" ); } } while (0); |
1350 | mConnecting = CONNECTING_IN_PROGRESS; |
1351 | |
1352 | if (aCalledFromAdmissionManager) { |
1353 | // When called from nsWSAdmissionManager post an event to avoid potential |
1354 | // re-entering of nsWSAdmissionManager and its lock. |
1355 | NS_DispatchToMainThread( |
1356 | NewRunnableMethod("net::WebSocketChannel::BeginOpenInternal", this, |
1357 | &WebSocketChannel::BeginOpenInternal), |
1358 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1359 | } else { |
1360 | BeginOpenInternal(); |
1361 | } |
1362 | } |
1363 | |
1364 | // MainThread |
1365 | void WebSocketChannel::BeginOpenInternal() { |
1366 | LOG(("WebSocketChannel::BeginOpenInternal() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal() %p\n" , this); } } while (0); |
1367 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1367); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1367; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1368 | |
1369 | nsresult rv; |
1370 | |
1371 | if (mRedirectCallback) { |
1372 | LOG(("WebSocketChannel::BeginOpenInternal: Resuming Redirect\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: Resuming Redirect\n" ); } } while (0); |
1373 | rv = mRedirectCallback->OnRedirectVerifyCallback(NS_OK); |
1374 | mRedirectCallback = nullptr; |
1375 | return; |
1376 | } |
1377 | |
1378 | nsCOMPtr<nsIChannel> localChannel = do_QueryInterface(mChannel, &rv); |
1379 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1380 | LOG(("WebSocketChannel::BeginOpenInternal: cannot async open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot async open\n" ); } } while (0); |
1381 | AbortSession(NS_ERROR_UNEXPECTED); |
1382 | return; |
1383 | } |
1384 | |
1385 | rv = localChannel->AsyncOpen(this); |
1386 | |
1387 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1388 | LOG(("WebSocketChannel::BeginOpenInternal: cannot async open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot async open\n" ); } } while (0); |
1389 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
1390 | return; |
1391 | } |
1392 | mOpenedHttpChannel = true; |
1393 | |
1394 | rv = NS_NewTimerWithCallback(getter_AddRefs(mOpenTimer), this, mOpenTimeout, |
1395 | nsITimer::TYPE_ONE_SHOT); |
1396 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1397 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open " "timer\n"); } } while (0) |
1398 | ("WebSocketChannel::BeginOpenInternal: cannot initialize open "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open " "timer\n"); } } while (0) |
1399 | "timer\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::BeginOpenInternal: cannot initialize open " "timer\n"); } } while (0); |
1400 | AbortSession(NS_ERROR_UNEXPECTED); |
1401 | return; |
1402 | } |
1403 | } |
1404 | |
1405 | bool WebSocketChannel::IsPersistentFramePtr() { |
1406 | return (mFramePtr >= mBuffer && mFramePtr < mBuffer + mBufferSize); |
1407 | } |
1408 | |
1409 | // Extends the internal buffer by count and returns the total |
1410 | // amount of data available for read |
1411 | // |
1412 | // Accumulated fragment size is passed in instead of using the member |
1413 | // variable beacuse when transitioning from the stack to the persistent |
1414 | // read buffer we want to explicitly include them in the buffer instead |
1415 | // of as already existing data. |
1416 | bool WebSocketChannel::UpdateReadBuffer(uint8_t* buffer, uint32_t count, |
1417 | uint32_t accumulatedFragments, |
1418 | uint32_t* available) { |
1419 | LOG(("WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n", this, buffer,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n" , this, buffer, count); } } while (0) |
1420 | count))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::UpdateReadBuffer() %p [%p %u]\n" , this, buffer, count); } } while (0); |
1421 | |
1422 | if (!mBuffered) mFramePtr = mBuffer; |
1423 | |
1424 | MOZ_ASSERT(IsPersistentFramePtr(), "update read buffer bad mFramePtr")do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsPersistentFramePtr())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsPersistentFramePtr()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("IsPersistentFramePtr()" " (" "update read buffer bad mFramePtr" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPersistentFramePtr()" ") (" "update read buffer bad mFramePtr" ")"); do { *((volatile int*)__null) = 1424; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1425 | MOZ_ASSERT(mFramePtr - accumulatedFragments >= mBuffer,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr - accumulatedFragments >= mBuffer)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mFramePtr - accumulatedFragments >= mBuffer))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("mFramePtr - accumulatedFragments >= mBuffer" " (" "reserved FramePtr bad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer" ") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null ) = 1426; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
1426 | "reserved FramePtr bad")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr - accumulatedFragments >= mBuffer)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mFramePtr - accumulatedFragments >= mBuffer))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("mFramePtr - accumulatedFragments >= mBuffer" " (" "reserved FramePtr bad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer" ") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null ) = 1426; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1427 | |
1428 | if (mBuffered + count <= mBufferSize) { |
1429 | // append to existing buffer |
1430 | LOG(("WebSocketChannel: update read buffer absorbed %u\n", count))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer absorbed %u\n" , count); } } while (0); |
1431 | } else if (mBuffered + count - (mFramePtr - accumulatedFragments - mBuffer) <= |
1432 | mBufferSize) { |
1433 | // make room in existing buffer by shifting unused data to start |
1434 | mBuffered -= (mFramePtr - mBuffer - accumulatedFragments); |
1435 | LOG(("WebSocketChannel: update read buffer shifted %u\n", mBuffered))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer shifted %u\n" , mBuffered); } } while (0); |
1436 | ::memmove(mBuffer, mFramePtr - accumulatedFragments, mBuffered); |
1437 | mFramePtr = mBuffer + accumulatedFragments; |
1438 | } else { |
1439 | // existing buffer is not sufficient, extend it |
1440 | mBufferSize += count + 8192 + mBufferSize / 3; |
1441 | LOG(("WebSocketChannel: update read buffer extended to %u\n", mBufferSize))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: update read buffer extended to %u\n" , mBufferSize); } } while (0); |
1442 | uint8_t* old = mBuffer; |
1443 | mBuffer = (uint8_t*)realloc(mBuffer, mBufferSize); |
1444 | if (!mBuffer) { |
1445 | mBuffer = old; |
1446 | return false; |
1447 | } |
1448 | mFramePtr = mBuffer + (mFramePtr - old); |
1449 | } |
1450 | |
1451 | ::memcpy(mBuffer + mBuffered, buffer, count); |
1452 | mBuffered += count; |
1453 | |
1454 | if (available) *available = mBuffered - (mFramePtr - mBuffer); |
1455 | |
1456 | return true; |
1457 | } |
1458 | |
1459 | nsresult WebSocketChannel::ProcessInput(uint8_t* buffer, uint32_t count) { |
1460 | LOG(("WebSocketChannel::ProcessInput %p [%d %d]\n", this, count, mBuffered))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput %p [%d %d]\n" , this, count, mBuffered); } } while (0); |
1461 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1461); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1461; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1462 | |
1463 | nsresult rv; |
1464 | |
1465 | // The purpose of ping/pong is to actively probe the peer so that an |
1466 | // unreachable peer is not mistaken for a period of idleness. This |
1467 | // implementation accepts any application level read activity as a sign of |
1468 | // life, it does not necessarily have to be a pong. |
1469 | ResetPingTimer(); |
1470 | |
1471 | uint32_t avail; |
1472 | |
1473 | if (!mBuffered) { |
1474 | // Most of the time we can process right off the stack buffer without |
1475 | // having to accumulate anything |
1476 | mFramePtr = buffer; |
1477 | avail = count; |
1478 | } else { |
1479 | if (!UpdateReadBuffer(buffer, count, mFragmentAccumulator, &avail)) { |
1480 | return NS_ERROR_FILE_TOO_BIG; |
1481 | } |
1482 | } |
1483 | |
1484 | uint8_t* payload; |
1485 | uint32_t totalAvail = avail; |
1486 | |
1487 | while (avail >= 2) { |
1488 | int64_t payloadLength64 = mFramePtr[1] & kPayloadLengthBitsMask; |
1489 | uint8_t finBit = mFramePtr[0] & kFinalFragBit; |
1490 | uint8_t rsvBits = mFramePtr[0] & kRsvBitsMask; |
1491 | uint8_t rsvBit1 = mFramePtr[0] & kRsv1Bit; |
1492 | uint8_t rsvBit2 = mFramePtr[0] & kRsv2Bit; |
1493 | uint8_t rsvBit3 = mFramePtr[0] & kRsv3Bit; |
1494 | uint8_t opcode = mFramePtr[0] & kOpcodeBitsMask; |
1495 | uint8_t maskBit = mFramePtr[1] & kMaskBit; |
1496 | uint32_t mask = 0; |
1497 | |
1498 | uint32_t framingLength = 2; |
1499 | if (maskBit) framingLength += 4; |
1500 | |
1501 | if (payloadLength64 < 126) { |
1502 | if (avail < framingLength) break; |
1503 | } else if (payloadLength64 == 126) { |
1504 | // 16 bit length field |
1505 | framingLength += 2; |
1506 | if (avail < framingLength) break; |
1507 | |
1508 | payloadLength64 = mFramePtr[2] << 8 | mFramePtr[3]; |
1509 | |
1510 | if (payloadLength64 < 126) { |
1511 | // Section 5.2 says that the minimal number of bytes MUST |
1512 | // be used to encode the length in all cases |
1513 | LOG(("WebSocketChannel:: non-minimal-encoded payload length"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: non-minimal-encoded payload length" ); } } while (0); |
1514 | return NS_ERROR_ILLEGAL_VALUE; |
1515 | } |
1516 | |
1517 | } else { |
1518 | // 64 bit length |
1519 | framingLength += 8; |
1520 | if (avail < framingLength) break; |
1521 | |
1522 | if (mFramePtr[2] & 0x80) { |
1523 | // Section 4.2 says that the most significant bit MUST be |
1524 | // 0. (i.e. this is really a 63 bit value) |
1525 | LOG(("WebSocketChannel:: high bit of 64 bit length set"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: high bit of 64 bit length set" ); } } while (0); |
1526 | return NS_ERROR_ILLEGAL_VALUE; |
1527 | } |
1528 | |
1529 | // copy this in case it is unaligned |
1530 | payloadLength64 = NetworkEndian::readInt64(mFramePtr + 2); |
1531 | |
1532 | if (payloadLength64 <= 0xffff) { |
1533 | // Section 5.2 says that the minimal number of bytes MUST |
1534 | // be used to encode the length in all cases |
1535 | LOG(("WebSocketChannel:: non-minimal-encoded payload length"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: non-minimal-encoded payload length" ); } } while (0); |
1536 | return NS_ERROR_ILLEGAL_VALUE; |
1537 | } |
1538 | } |
1539 | |
1540 | payload = mFramePtr + framingLength; |
1541 | avail -= framingLength; |
1542 | |
1543 | LOG(("WebSocketChannel::ProcessInput: payload %" PRId64 " avail %" PRIu32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %" "l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while (0) |
1544 | "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %" "l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while (0) |
1545 | payloadLength64, avail))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: payload %" "l" "d" " avail %" "u" "\n", payloadLength64, avail); } } while (0); |
1546 | |
1547 | CheckedInt<int64_t> payloadLengthChecked(payloadLength64); |
1548 | payloadLengthChecked += mFragmentAccumulator; |
1549 | if (!payloadLengthChecked.isValid() || |
1550 | payloadLengthChecked.value() > mMaxMessageSize) { |
1551 | return NS_ERROR_FILE_TOO_BIG; |
1552 | } |
1553 | |
1554 | uint32_t payloadLength = static_cast<uint32_t>(payloadLength64); |
1555 | |
1556 | if (avail < payloadLength) break; |
1557 | |
1558 | LOG(("WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n" , opcode); } } while (0) |
1559 | opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: Frame accumulated - opcode %d\n" , opcode); } } while (0); |
1560 | |
1561 | if (!maskBit && mIsServerSide) { |
1562 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received " "from client\n"); } } while (0) |
1563 | ("WebSocketChannel::ProcessInput: unmasked frame received "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received " "from client\n"); } } while (0) |
1564 | "from client\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unmasked frame received " "from client\n"); } } while (0); |
1565 | return NS_ERROR_ILLEGAL_VALUE; |
1566 | } |
1567 | |
1568 | if (maskBit) { |
1569 | if (!mIsServerSide) { |
1570 | // The server should not be allowed to send masked frames to clients. |
1571 | // But we've been allowing it for some time, so this should be |
1572 | // deprecated with care. |
1573 | LOG(("WebSocketChannel:: Client RECEIVING masked frame."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Client RECEIVING masked frame." ); } } while (0); |
1574 | } |
1575 | |
1576 | mask = NetworkEndian::readUint32(payload - 4); |
1577 | } |
1578 | |
1579 | if (mask) { |
1580 | ApplyMask(mask, payload, payloadLength); |
1581 | } else if (mIsServerSide) { |
1582 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received" "from client\n"); } } while (0) |
1583 | ("WebSocketChannel::ProcessInput: masked frame with mask 0 received"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received" "from client\n"); } } while (0) |
1584 | "from client\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: masked frame with mask 0 received" "from client\n"); } } while (0); |
1585 | return NS_ERROR_ILLEGAL_VALUE; |
1586 | } |
1587 | |
1588 | // Control codes are required to have the fin bit set |
1589 | if (!finBit && (opcode & kControlFrameMask)) { |
1590 | LOG(("WebSocketChannel:: fragmented control frame code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: fragmented control frame code %d\n" , opcode); } } while (0); |
1591 | return NS_ERROR_ILLEGAL_VALUE; |
1592 | } |
1593 | |
1594 | if (rsvBits) { |
1595 | // PMCE sets RSV1 bit in the first fragment when the non-control frame |
1596 | // is deflated |
1597 | MutexAutoLock lock(mCompressorMutex); |
1598 | if (mPMCECompressor && rsvBits == kRsv1Bit && mFragmentAccumulator == 0 && |
1599 | !(opcode & kControlFrameMask)) { |
1600 | mPMCECompressor->SetMessageDeflated(); |
1601 | LOG(("WebSocketChannel::ProcessInput: received deflated frame\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: received deflated frame\n" ); } } while (0); |
1602 | } else { |
1603 | LOG(("WebSocketChannel::ProcessInput: unexpected reserved bits %x\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unexpected reserved bits %x\n" , rsvBits); } } while (0) |
1604 | rsvBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ProcessInput: unexpected reserved bits %x\n" , rsvBits); } } while (0); |
1605 | return NS_ERROR_ILLEGAL_VALUE; |
1606 | } |
1607 | } |
1608 | |
1609 | if (!finBit || opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1610 | // This is part of a fragment response |
1611 | |
1612 | // Only the first frame has a non zero op code: Make sure we don't see a |
1613 | // first frame while some old fragments are open |
1614 | if ((mFragmentAccumulator != 0) && |
1615 | (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION)) { |
1616 | LOG(("WebSocketChannel:: nested fragments\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: nested fragments\n" ); } } while (0); |
1617 | return NS_ERROR_ILLEGAL_VALUE; |
1618 | } |
1619 | |
1620 | LOG(("WebSocketChannel:: Accumulating Fragment %" PRIu32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Accumulating Fragment %" "u" "\n", payloadLength); } } while (0) |
1621 | payloadLength))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Accumulating Fragment %" "u" "\n", payloadLength); } } while (0); |
1622 | |
1623 | if (opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1624 | // Make sure this continuation fragment isn't the first fragment |
1625 | if (mFragmentOpcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1626 | LOG(("WebSocketHeandler:: continuation code in first fragment\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketHeandler:: continuation code in first fragment\n" ); } } while (0); |
1627 | return NS_ERROR_ILLEGAL_VALUE; |
1628 | } |
1629 | |
1630 | // For frag > 1 move the data body back on top of the headers |
1631 | // so we have contiguous stream of data |
1632 | MOZ_ASSERT(mFramePtr + framingLength == payload,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1633; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
1633 | "payload offset from frameptr wrong")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1633; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1634 | ::memmove(mFramePtr, payload, avail); |
1635 | payload = mFramePtr; |
1636 | if (mBuffered) mBuffered -= framingLength; |
1637 | } else { |
1638 | mFragmentOpcode = opcode; |
1639 | } |
1640 | |
1641 | if (finBit) { |
1642 | LOG(("WebSocketChannel:: Finalizing Fragment\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Finalizing Fragment\n" ); } } while (0); |
1643 | payload -= mFragmentAccumulator; |
1644 | payloadLength += mFragmentAccumulator; |
1645 | avail += mFragmentAccumulator; |
1646 | mFragmentAccumulator = 0; |
1647 | opcode = mFragmentOpcode; |
1648 | // reset to detect if next message illegally starts with continuation |
1649 | mFragmentOpcode = nsIWebSocketFrame::OPCODE_CONTINUATION; |
1650 | } else { |
1651 | opcode = nsIWebSocketFrame::OPCODE_CONTINUATION; |
1652 | mFragmentAccumulator += payloadLength; |
1653 | } |
1654 | } else if (mFragmentAccumulator != 0 && !(opcode & kControlFrameMask)) { |
1655 | // This frame is not part of a fragment sequence but we |
1656 | // have an open fragment.. it must be a control code or else |
1657 | // we have a problem |
1658 | LOG(("WebSocketChannel:: illegal fragment sequence\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: illegal fragment sequence\n" ); } } while (0); |
1659 | return NS_ERROR_ILLEGAL_VALUE; |
1660 | } |
1661 | |
1662 | if (mServerClosed) { |
1663 | LOG(("WebSocketChannel:: ignoring read frame code %d after close\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after close\n" , opcode); } } while (0) |
1664 | opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after close\n" , opcode); } } while (0); |
1665 | // nop |
1666 | } else if (mStopped) { |
1667 | LOG(("WebSocketChannel:: ignoring read frame code %d after completion\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after completion\n" , opcode); } } while (0) |
1668 | opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ignoring read frame code %d after completion\n" , opcode); } } while (0); |
1669 | } else if (opcode == nsIWebSocketFrame::OPCODE_TEXT) { |
1670 | if (mListenerMT) { |
1671 | nsCString utf8Data; |
1672 | { |
1673 | MutexAutoLock lock(mCompressorMutex); |
1674 | bool isDeflated = |
1675 | mPMCECompressor && mPMCECompressor->IsMessageDeflated(); |
1676 | LOG(("WebSocketChannel:: %stext frame received\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %stext frame received\n" , isDeflated ? "deflated " : ""); } } while (0) |
1677 | isDeflated ? "deflated " : ""))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %stext frame received\n" , isDeflated ? "deflated " : ""); } } while (0); |
1678 | |
1679 | if (isDeflated) { |
1680 | rv = mPMCECompressor->Inflate(payload, payloadLength, utf8Data); |
1681 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1682 | return rv; |
1683 | } |
1684 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0) |
1685 | ("WebSocketChannel:: message successfully inflated "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0) |
1686 | "[origLength=%d, newLength=%zd]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0) |
1687 | payloadLength, utf8Data.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, utf8Data. Length()); } } while (0); |
1688 | } else { |
1689 | if (!utf8Data.Assign((const char*)payload, payloadLength, |
1690 | mozilla::fallible)) { |
1691 | return NS_ERROR_OUT_OF_MEMORY; |
1692 | } |
1693 | } |
1694 | } |
1695 | |
1696 | // Section 8.1 says to fail connection if invalid utf-8 in text message |
1697 | if (!IsUtf8(utf8Data)) { |
1698 | LOG(("WebSocketChannel:: text frame invalid utf-8\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: text frame invalid utf-8\n" ); } } while (0); |
1699 | return NS_ERROR_CANNOT_CONVERT_DATA; |
1700 | } |
1701 | |
1702 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
1703 | finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, utf8Data); |
1704 | |
1705 | if (frame) { |
1706 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1707 | } |
1708 | |
1709 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1710 | target->Dispatch(new CallOnMessageAvailable(this, utf8Data, -1), |
1711 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1712 | } else { |
1713 | return NS_ERROR_UNEXPECTED; |
1714 | } |
1715 | if (mConnectionLogService && !mPrivateBrowsing) { |
1716 | mConnectionLogService->NewMsgReceived(mHost, mSerial, count); |
1717 | LOG(("Added new msg received for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new msg received for %s" , mHost.get()); } } while (0); |
1718 | } |
1719 | } |
1720 | } else if (opcode & kControlFrameMask) { |
1721 | // control frames |
1722 | if (payloadLength > 125) { |
1723 | LOG(("WebSocketChannel:: bad control frame code %d length %d\n", opcode,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: bad control frame code %d length %d\n" , opcode, payloadLength); } } while (0) |
1724 | payloadLength))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: bad control frame code %d length %d\n" , opcode, payloadLength); } } while (0); |
1725 | return NS_ERROR_ILLEGAL_VALUE; |
1726 | } |
1727 | |
1728 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
1729 | finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, payload, |
1730 | payloadLength); |
1731 | |
1732 | if (opcode == nsIWebSocketFrame::OPCODE_CLOSE) { |
1733 | LOG(("WebSocketChannel:: close received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close received\n" ); } } while (0); |
1734 | mServerClosed = true; |
1735 | |
1736 | mServerCloseCode = CLOSE_NO_STATUS; |
1737 | if (payloadLength >= 2) { |
1738 | mServerCloseCode = NetworkEndian::readUint16(payload); |
1739 | LOG(("WebSocketChannel:: close recvd code %u\n", mServerCloseCode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close recvd code %u\n" , mServerCloseCode); } } while (0); |
1740 | uint16_t msglen = static_cast<uint16_t>(payloadLength - 2); |
1741 | if (msglen > 0) { |
1742 | mServerCloseReason.SetLength(msglen); |
1743 | memcpy(mServerCloseReason.BeginWriting(), (const char*)payload + 2, |
1744 | msglen); |
1745 | |
1746 | // section 8.1 says to replace received non utf-8 sequences |
1747 | // (which are non-conformant to send) with u+fffd, |
1748 | // but secteam feels that silently rewriting messages is |
1749 | // inappropriate - so we will fail the connection instead. |
1750 | if (!IsUtf8(mServerCloseReason)) { |
1751 | LOG(("WebSocketChannel:: close frame invalid utf-8\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close frame invalid utf-8\n" ); } } while (0); |
1752 | return NS_ERROR_CANNOT_CONVERT_DATA; |
1753 | } |
1754 | |
1755 | LOG(("WebSocketChannel:: close msg %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close msg %s\n" , mServerCloseReason.get()); } } while (0) |
1756 | mServerCloseReason.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: close msg %s\n" , mServerCloseReason.get()); } } while (0); |
1757 | } |
1758 | } |
1759 | |
1760 | if (mCloseTimer) { |
1761 | mCloseTimer->Cancel(); |
1762 | mCloseTimer = nullptr; |
1763 | } |
1764 | |
1765 | if (frame) { |
1766 | // We send the frame immediately becuase we want to have it dispatched |
1767 | // before the CallOnServerClose. |
1768 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1769 | frame = nullptr; |
1770 | } |
1771 | |
1772 | if (mListenerMT) { |
1773 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1774 | target->Dispatch(new CallOnServerClose(this, mServerCloseCode, |
1775 | mServerCloseReason), |
1776 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1777 | } else { |
1778 | return NS_ERROR_UNEXPECTED; |
1779 | } |
1780 | } |
1781 | |
1782 | if (mClientClosed) ReleaseSession(); |
1783 | } else if (opcode == nsIWebSocketFrame::OPCODE_PING) { |
1784 | LOG(("WebSocketChannel:: ping received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: ping received\n" ); } } while (0); |
1785 | GeneratePong(payload, payloadLength); |
1786 | } else if (opcode == nsIWebSocketFrame::OPCODE_PONG) { |
1787 | // opcode OPCODE_PONG: the mere act of receiving the packet is all we |
1788 | // need to do for the pong to trigger the activity timers |
1789 | LOG(("WebSocketChannel:: pong received\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: pong received\n" ); } } while (0); |
1790 | } else { |
1791 | /* unknown control frame opcode */ |
1792 | LOG(("WebSocketChannel:: unknown control op code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: unknown control op code %d\n" , opcode); } } while (0); |
1793 | return NS_ERROR_ILLEGAL_VALUE; |
1794 | } |
1795 | |
1796 | if (mFragmentAccumulator) { |
1797 | // Remove the control frame from the stream so we have a contiguous |
1798 | // data buffer of reassembled fragments |
1799 | LOG(("WebSocketChannel:: Removing Control From Read buffer\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Removing Control From Read buffer\n" ); } } while (0); |
1800 | MOZ_ASSERT(mFramePtr + framingLength == payload,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1801; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
1801 | "payload offset from frameptr wrong")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFramePtr + framingLength == payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFramePtr + framingLength == payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mFramePtr + framingLength == payload" " (" "payload offset from frameptr wrong" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1801; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1802 | ::memmove(mFramePtr, payload + payloadLength, avail - payloadLength); |
1803 | payload = mFramePtr; |
1804 | avail -= payloadLength; |
1805 | if (mBuffered) mBuffered -= framingLength + payloadLength; |
1806 | payloadLength = 0; |
1807 | } |
1808 | |
1809 | if (frame) { |
1810 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1811 | } |
1812 | } else if (opcode == nsIWebSocketFrame::OPCODE_BINARY) { |
1813 | if (mListenerMT) { |
1814 | nsCString binaryData; |
1815 | { |
1816 | MutexAutoLock lock(mCompressorMutex); |
1817 | bool isDeflated = |
1818 | mPMCECompressor && mPMCECompressor->IsMessageDeflated(); |
1819 | LOG(("WebSocketChannel:: %sbinary frame received\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %sbinary frame received\n" , isDeflated ? "deflated " : ""); } } while (0) |
1820 | isDeflated ? "deflated " : ""))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: %sbinary frame received\n" , isDeflated ? "deflated " : ""); } } while (0); |
1821 | |
1822 | if (isDeflated) { |
1823 | rv = mPMCECompressor->Inflate(payload, payloadLength, binaryData); |
1824 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1825 | return rv; |
1826 | } |
1827 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0) |
1828 | ("WebSocketChannel:: message successfully inflated "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0) |
1829 | "[origLength=%d, newLength=%zd]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0) |
1830 | payloadLength, binaryData.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: message successfully inflated " "[origLength=%d, newLength=%zd]\n", payloadLength, binaryData .Length()); } } while (0); |
1831 | } else { |
1832 | if (!binaryData.Assign((const char*)payload, payloadLength, |
1833 | mozilla::fallible)) { |
1834 | return NS_ERROR_OUT_OF_MEMORY; |
1835 | } |
1836 | } |
1837 | } |
1838 | |
1839 | RefPtr<WebSocketFrame> frame = |
1840 | mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, |
1841 | opcode, maskBit, mask, binaryData); |
1842 | if (frame) { |
1843 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1844 | } |
1845 | |
1846 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1847 | target->Dispatch( |
1848 | new CallOnMessageAvailable(this, binaryData, binaryData.Length()), |
1849 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1850 | } else { |
1851 | return NS_ERROR_UNEXPECTED; |
1852 | } |
1853 | // To add the header to 'Networking Dashboard' log |
1854 | if (mConnectionLogService && !mPrivateBrowsing) { |
1855 | mConnectionLogService->NewMsgReceived(mHost, mSerial, count); |
1856 | LOG(("Added new received msg for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new received msg for %s" , mHost.get()); } } while (0); |
1857 | } |
1858 | } |
1859 | } else if (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1860 | /* unknown opcode */ |
1861 | LOG(("WebSocketChannel:: unknown op code %d\n", opcode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: unknown op code %d\n" , opcode); } } while (0); |
1862 | return NS_ERROR_ILLEGAL_VALUE; |
1863 | } |
1864 | |
1865 | mFramePtr = payload + payloadLength; |
1866 | avail -= payloadLength; |
1867 | totalAvail = avail; |
1868 | } |
1869 | |
1870 | // Adjust the stateful buffer. If we were operating off the stack and |
1871 | // now have a partial message then transition to the buffer, or if |
1872 | // we were working off the buffer but no longer have any active state |
1873 | // then transition to the stack |
1874 | if (!IsPersistentFramePtr()) { |
1875 | mBuffered = 0; |
1876 | |
1877 | if (mFragmentAccumulator) { |
1878 | LOG(("WebSocketChannel:: Setup Buffer due to fragment"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Setup Buffer due to fragment" ); } } while (0); |
1879 | |
1880 | if (!UpdateReadBuffer(mFramePtr - mFragmentAccumulator, |
1881 | totalAvail + mFragmentAccumulator, 0, nullptr)) { |
1882 | return NS_ERROR_FILE_TOO_BIG; |
1883 | } |
1884 | |
1885 | // UpdateReadBuffer will reset the frameptr to the beginning |
1886 | // of new saved state, so we need to skip past processed framgents |
1887 | mFramePtr += mFragmentAccumulator; |
1888 | } else if (totalAvail) { |
1889 | LOG(("WebSocketChannel:: Setup Buffer due to partial frame"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Setup Buffer due to partial frame" ); } } while (0); |
1890 | if (!UpdateReadBuffer(mFramePtr, totalAvail, 0, nullptr)) { |
1891 | return NS_ERROR_FILE_TOO_BIG; |
1892 | } |
1893 | } |
1894 | } else if (!mFragmentAccumulator && !totalAvail) { |
1895 | // If we were working off a saved buffer state and there is no partial |
1896 | // frame or fragment in process, then revert to stack behavior |
1897 | LOG(("WebSocketChannel:: Internal buffering not needed anymore"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Internal buffering not needed anymore" ); } } while (0); |
1898 | mBuffered = 0; |
1899 | |
1900 | // release memory if we've been processing a large message |
1901 | if (mBufferSize > kIncomingBufferStableSize) { |
1902 | mBufferSize = kIncomingBufferStableSize; |
1903 | free(mBuffer); |
1904 | mBuffer = (uint8_t*)moz_xmalloc(mBufferSize); |
1905 | } |
1906 | } |
1907 | return NS_OK; |
1908 | } |
1909 | |
1910 | /* static */ |
1911 | void WebSocketChannel::ApplyMask(uint32_t mask, uint8_t* data, uint64_t len) { |
1912 | if (!data || len == 0) return; |
1913 | |
1914 | // Optimally we want to apply the mask 32 bits at a time, |
1915 | // but the buffer might not be alligned. So we first deal with |
1916 | // 0 to 3 bytes of preamble individually |
1917 | |
1918 | while (len && (reinterpret_cast<uintptr_t>(data) & 3)) { |
1919 | *data ^= mask >> 24; |
1920 | mask = RotateLeft(mask, 8); |
1921 | data++; |
1922 | len--; |
1923 | } |
1924 | |
1925 | // perform mask on full words of data |
1926 | |
1927 | uint32_t* iData = (uint32_t*)data; |
1928 | uint32_t* end = iData + (len / 4); |
1929 | NetworkEndian::writeUint32(&mask, mask); |
1930 | for (; iData < end; iData++) *iData ^= mask; |
1931 | mask = NetworkEndian::readUint32(&mask); |
1932 | data = (uint8_t*)iData; |
1933 | len = len % 4; |
1934 | |
1935 | // There maybe up to 3 trailing bytes that need to be dealt with |
1936 | // individually |
1937 | |
1938 | while (len) { |
1939 | *data ^= mask >> 24; |
1940 | mask = RotateLeft(mask, 8); |
1941 | data++; |
1942 | len--; |
1943 | } |
1944 | } |
1945 | |
1946 | void WebSocketChannel::GeneratePing() { |
1947 | nsAutoCString buf; |
1948 | buf.AssignLiteral("PING"); |
1949 | EnqueueOutgoingMessage(mOutgoingPingMessages, |
1950 | new OutboundMessage(kMsgTypePing, buf)); |
1951 | } |
1952 | |
1953 | void WebSocketChannel::GeneratePong(uint8_t* payload, uint32_t len) { |
1954 | nsAutoCString buf; |
1955 | buf.SetLength(len); |
1956 | if (buf.Length() < len) { |
1957 | LOG(("WebSocketChannel::GeneratePong Allocation Failure\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GeneratePong Allocation Failure\n" ); } } while (0); |
1958 | return; |
1959 | } |
1960 | |
1961 | memcpy(buf.BeginWriting(), payload, len); |
1962 | EnqueueOutgoingMessage(mOutgoingPongMessages, |
1963 | new OutboundMessage(kMsgTypePong, buf)); |
1964 | } |
1965 | |
1966 | void WebSocketChannel::EnqueueOutgoingMessage(nsDeque<OutboundMessage>& aQueue, |
1967 | OutboundMessage* aMsg) { |
1968 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 1968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1968; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1969 | |
1970 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0) |
1971 | ("WebSocketChannel::EnqueueOutgoingMessage %p "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0) |
1972 | "queueing msg %p [type=%s len=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0) |
1973 | this, aMsg, msgNames[aMsg->GetMsgType()], aMsg->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnqueueOutgoingMessage %p " "queueing msg %p [type=%s len=%d]\n", this, aMsg, msgNames[aMsg ->GetMsgType()], aMsg->Length()); } } while (0); |
1974 | |
1975 | aQueue.Push(aMsg); |
1976 | if (mSocketOut) { |
1977 | OnOutputStreamReady(mSocketOut); |
1978 | } else { |
1979 | DoEnqueueOutgoingMessage(); |
1980 | } |
1981 | } |
1982 | |
1983 | uint16_t WebSocketChannel::ResultToCloseCode(nsresult resultCode) { |
1984 | if (NS_SUCCEEDED(resultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(resultCode)), 1)) )) return CLOSE_NORMAL; |
1985 | |
1986 | switch (resultCode) { |
1987 | case NS_ERROR_FILE_TOO_BIG: |
1988 | case NS_ERROR_OUT_OF_MEMORY: |
1989 | return CLOSE_TOO_LARGE; |
1990 | case NS_ERROR_CANNOT_CONVERT_DATA: |
1991 | return CLOSE_INVALID_PAYLOAD; |
1992 | case NS_ERROR_UNEXPECTED: |
1993 | return CLOSE_INTERNAL_ERROR; |
1994 | default: |
1995 | return CLOSE_PROTOCOL_ERROR; |
1996 | } |
1997 | } |
1998 | |
1999 | void WebSocketChannel::PrimeNewOutgoingMessage() { |
2000 | LOG(("WebSocketChannel::PrimeNewOutgoingMessage() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage() %p\n" , this); } } while (0); |
2001 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 2001; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2002 | MOZ_ASSERT(!mCurrentOut, "Current message in progress")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCurrentOut)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCurrentOut))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCurrentOut" " (" "Current message in progress" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCurrentOut" ") (" "Current message in progress" ")"); do { *((volatile int *)__null) = 2002; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2003 | |
2004 | nsresult rv = NS_OK; |
2005 | |
2006 | mCurrentOut = mOutgoingPongMessages.PopFront(); |
2007 | if (mCurrentOut) { |
2008 | MOZ_ASSERT(mCurrentOut->GetMsgType() == kMsgTypePong, "Not pong message!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCurrentOut->GetMsgType() == kMsgTypePong)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mCurrentOut->GetMsgType() == kMsgTypePong))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePong" " (" "Not pong message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePong" ") (" "Not pong message!" ")"); do { *((volatile int*)__null ) = 2008; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2009 | } else { |
2010 | mCurrentOut = mOutgoingPingMessages.PopFront(); |
2011 | if (mCurrentOut) { |
2012 | MOZ_ASSERT(mCurrentOut->GetMsgType() == kMsgTypePing,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCurrentOut->GetMsgType() == kMsgTypePing)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mCurrentOut->GetMsgType() == kMsgTypePing))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePing" " (" "Not ping message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing" ") (" "Not ping message!" ")"); do { *((volatile int*)__null ) = 2013; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
2013 | "Not ping message!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCurrentOut->GetMsgType() == kMsgTypePing)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mCurrentOut->GetMsgType() == kMsgTypePing))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCurrentOut->GetMsgType() == kMsgTypePing" " (" "Not ping message!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing" ") (" "Not ping message!" ")"); do { *((volatile int*)__null ) = 2013; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2014 | } else { |
2015 | mCurrentOut = mOutgoingMessages.PopFront(); |
2016 | } |
2017 | } |
2018 | |
2019 | if (!mCurrentOut) return; |
2020 | |
2021 | auto cleanupAfterFailure = |
2022 | MakeScopeExit([&] { DeleteCurrentOutGoingMessage(); }); |
2023 | |
2024 | WsMsgType msgType = mCurrentOut->GetMsgType(); |
2025 | |
2026 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0) |
2027 | ("WebSocketChannel::PrimeNewOutgoingMessage "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0) |
2028 | "%p found queued msg %p [type=%s len=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0) |
2029 | this, mCurrentOut, msgNames[msgType], mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage " "%p found queued msg %p [type=%s len=%d]\n", this, mCurrentOut , msgNames[msgType], mCurrentOut->Length()); } } while (0); |
2030 | |
2031 | mCurrentOutSent = 0; |
2032 | mHdrOut = mOutHeader; |
2033 | |
2034 | uint8_t maskBit = mIsServerSide ? 0 : kMaskBit; |
2035 | uint8_t maskSize = mIsServerSide ? 0 : 4; |
2036 | |
2037 | uint8_t* payload = nullptr; |
2038 | |
2039 | if (msgType == kMsgTypeFin) { |
2040 | // This is a demand to create a close message |
2041 | if (mClientClosed) { |
2042 | DeleteCurrentOutGoingMessage(); |
2043 | PrimeNewOutgoingMessage(); |
2044 | cleanupAfterFailure.release(); |
2045 | return; |
2046 | } |
2047 | |
2048 | mClientClosed = true; |
2049 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_CLOSE; |
2050 | mOutHeader[1] = maskBit; |
2051 | |
2052 | // payload is offset 2 plus size of the mask |
2053 | payload = mOutHeader + 2 + maskSize; |
2054 | |
2055 | // The close reason code sits in the first 2 bytes of payload |
2056 | // If the channel user provided a code and reason during Close() |
2057 | // and there isn't an internal error, use that. |
2058 | if (NS_SUCCEEDED(mStopOnClose)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStopOnClose)), 1 )))) { |
2059 | MutexAutoLock lock(mMutex); |
2060 | if (mScriptCloseCode) { |
2061 | NetworkEndian::writeUint16(payload, mScriptCloseCode); |
2062 | mOutHeader[1] += 2; |
2063 | mHdrOutToSend = 4 + maskSize; |
2064 | if (!mScriptCloseReason.IsEmpty()) { |
2065 | MOZ_ASSERT(mScriptCloseReason.Length() <= 123,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mScriptCloseReason.Length() <= 123)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(mScriptCloseReason.Length() <= 123))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mScriptCloseReason.Length() <= 123" " (" "Close Reason Too Long" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123" ") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null ) = 2066; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
2066 | "Close Reason Too Long")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mScriptCloseReason.Length() <= 123)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(mScriptCloseReason.Length() <= 123))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mScriptCloseReason.Length() <= 123" " (" "Close Reason Too Long" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123" ") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null ) = 2066; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2067 | mOutHeader[1] += mScriptCloseReason.Length(); |
2068 | mHdrOutToSend += mScriptCloseReason.Length(); |
2069 | memcpy(payload + 2, mScriptCloseReason.BeginReading(), |
2070 | mScriptCloseReason.Length()); |
2071 | } |
2072 | } else { |
2073 | // No close code/reason, so payload length = 0. We must still send mask |
2074 | // even though it's not used. Keep payload offset so we write mask |
2075 | // below. |
2076 | mHdrOutToSend = 2 + maskSize; |
2077 | } |
2078 | } else { |
2079 | NetworkEndian::writeUint16(payload, ResultToCloseCode(mStopOnClose)); |
2080 | mOutHeader[1] += 2; |
2081 | mHdrOutToSend = 4 + maskSize; |
2082 | } |
2083 | |
2084 | if (mServerClosed) { |
2085 | /* bidi close complete */ |
2086 | mReleaseOnTransmit = 1; |
2087 | } else if (NS_FAILED(mStopOnClose)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStopOnClose)), 0) ))) { |
2088 | /* result of abort session - give up */ |
2089 | StopSession(mStopOnClose); |
2090 | } else { |
2091 | /* wait for reciprocal close from server */ |
2092 | rv = NS_NewTimerWithCallback(getter_AddRefs(mCloseTimer), this, |
2093 | mCloseTimeout, nsITimer::TYPE_ONE_SHOT); |
2094 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2095 | StopSession(rv); |
2096 | } |
2097 | } |
2098 | } else { |
2099 | switch (msgType) { |
2100 | case kMsgTypePong: |
2101 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PONG; |
2102 | break; |
2103 | case kMsgTypePing: |
2104 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PING; |
2105 | break; |
2106 | case kMsgTypeString: |
2107 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_TEXT; |
2108 | break; |
2109 | case kMsgTypeStream: |
2110 | // HACK ALERT: read in entire stream into string. |
2111 | // Will block socket transport thread if file is blocking. |
2112 | // TODO: bug 704447: don't block socket thread! |
2113 | rv = mCurrentOut->ConvertStreamToString(); |
2114 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2115 | AbortSession(NS_ERROR_FILE_TOO_BIG); |
2116 | return; |
2117 | } |
2118 | // Now we're a binary string |
2119 | msgType = kMsgTypeBinaryString; |
2120 | |
2121 | // no break: fall down into binary string case |
2122 | [[fallthrough]]; |
2123 | |
2124 | case kMsgTypeBinaryString: |
2125 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_BINARY; |
2126 | break; |
2127 | case kMsgTypeFin: |
2128 | MOZ_ASSERT(false, "unreachable")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "unreachable" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2128); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "unreachable" ")"); do { *((volatile int*)__null) = 2128; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); // avoid compiler warning |
2129 | break; |
2130 | } |
2131 | |
2132 | // deflate the payload if PMCE is negotiated |
2133 | MutexAutoLock lock(mCompressorMutex); |
2134 | if (mPMCECompressor && |
2135 | (msgType == kMsgTypeString || msgType == kMsgTypeBinaryString)) { |
2136 | if (mCurrentOut->DeflatePayload(mPMCECompressor.get())) { |
2137 | // The payload was deflated successfully, set RSV1 bit |
2138 | mOutHeader[0] |= kRsv1Bit; |
2139 | |
2140 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2141 | ("WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2142 | "deflated [origLength=%d, newLength=%d].\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2143 | this, mCurrentOut, mCurrentOut->OrigLength(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0) |
2144 | mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage %p current msg %p was " "deflated [origLength=%d, newLength=%d].\n", this, mCurrentOut , mCurrentOut->OrigLength(), mCurrentOut->Length()); } } while (0); |
2145 | } |
2146 | } |
2147 | |
2148 | if (mCurrentOut->Length() < 126) { |
2149 | mOutHeader[1] = mCurrentOut->Length() | maskBit; |
2150 | mHdrOutToSend = 2 + maskSize; |
2151 | } else if (mCurrentOut->Length() <= 0xffff) { |
2152 | mOutHeader[1] = 126 | maskBit; |
2153 | NetworkEndian::writeUint16(mOutHeader + sizeof(uint16_t), |
2154 | mCurrentOut->Length()); |
2155 | mHdrOutToSend = 4 + maskSize; |
2156 | } else { |
2157 | mOutHeader[1] = 127 | maskBit; |
2158 | NetworkEndian::writeUint64(mOutHeader + 2, mCurrentOut->Length()); |
2159 | mHdrOutToSend = 10 + maskSize; |
2160 | } |
2161 | payload = mOutHeader + mHdrOutToSend; |
2162 | } |
2163 | |
2164 | MOZ_ASSERT(payload, "payload offset not found")do { static_assert( mozilla::detail::AssertionConditionType< decltype(payload)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(payload))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("payload" " (" "payload offset not found" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "payload" ") (" "payload offset not found" ")"); do { *((volatile int*)__null ) = 2164; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2165 | |
2166 | uint32_t mask = 0; |
2167 | if (!mIsServerSide) { |
2168 | // Perform the sending mask. Never use a zero mask |
2169 | do { |
2170 | static_assert(4 == sizeof(mask), "Size of the mask should be equal to 4"); |
2171 | nsresult rv = mRandomGenerator->GenerateRandomBytesInto(mask); |
2172 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2173 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0) |
2174 | ("WebSocketChannel::PrimeNewOutgoingMessage(): "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0) |
2175 | "GenerateRandomBytes failure %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0) |
2176 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage(): " "GenerateRandomBytes failure %" "x" "\n", static_cast<uint32_t >(rv)); } } while (0); |
2177 | AbortSession(rv); |
2178 | return; |
2179 | } |
2180 | } while (!mask); |
2181 | NetworkEndian::writeUint32(payload - sizeof(uint32_t), mask); |
2182 | } |
2183 | |
2184 | LOG(("WebSocketChannel::PrimeNewOutgoingMessage() using mask %08x\n", mask))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::PrimeNewOutgoingMessage() using mask %08x\n" , mask); } } while (0); |
2185 | |
2186 | // We don't mask the framing, but occasionally we stick a little payload |
2187 | // data in the buffer used for the framing. Close frames are the current |
2188 | // example. This data needs to be masked, but it is never more than a |
2189 | // handful of bytes and might rotate the mask, so we can just do it locally. |
2190 | // For real data frames we ship the bulk of the payload off to ApplyMask() |
2191 | |
2192 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
2193 | mOutHeader[0] & WebSocketChannel::kFinalFragBit, |
2194 | mOutHeader[0] & WebSocketChannel::kRsv1Bit, |
2195 | mOutHeader[0] & WebSocketChannel::kRsv2Bit, |
2196 | mOutHeader[0] & WebSocketChannel::kRsv3Bit, |
2197 | mOutHeader[0] & WebSocketChannel::kOpcodeBitsMask, |
2198 | mOutHeader[1] & WebSocketChannel::kMaskBit, mask, payload, |
2199 | mHdrOutToSend - (payload - mOutHeader), mCurrentOut->BeginOrigReading(), |
2200 | mCurrentOut->OrigLength()); |
2201 | |
2202 | if (frame) { |
2203 | mService->FrameSent(mSerial, mInnerWindowID, frame.forget()); |
2204 | } |
2205 | |
2206 | if (mask) { |
2207 | while (payload < (mOutHeader + mHdrOutToSend)) { |
2208 | *payload ^= mask >> 24; |
2209 | mask = RotateLeft(mask, 8); |
2210 | payload++; |
2211 | } |
2212 | |
2213 | // Mask the real message payloads |
2214 | ApplyMask(mask, mCurrentOut->BeginWriting(), mCurrentOut->Length()); |
2215 | } |
2216 | |
2217 | int32_t len = mCurrentOut->Length(); |
2218 | |
2219 | // for small frames, copy it all together for a contiguous write |
2220 | if (len && len <= kCopyBreak) { |
2221 | memcpy(mOutHeader + mHdrOutToSend, mCurrentOut->BeginWriting(), len); |
2222 | mHdrOutToSend += len; |
2223 | mCurrentOutSent = len; |
2224 | } |
2225 | |
2226 | // Transmitting begins - mHdrOutToSend bytes from mOutHeader and |
2227 | // mCurrentOut->Length() bytes from mCurrentOut. The latter may be |
2228 | // coaleseced into the former for small messages or as the result of the |
2229 | // compression process. |
2230 | |
2231 | cleanupAfterFailure.release(); |
2232 | } |
2233 | |
2234 | void WebSocketChannel::DeleteCurrentOutGoingMessage() { |
2235 | delete mCurrentOut; |
2236 | mCurrentOut = nullptr; |
2237 | mCurrentOutSent = 0; |
2238 | } |
2239 | |
2240 | void WebSocketChannel::EnsureHdrOut(uint32_t size) { |
2241 | LOG(("WebSocketChannel::EnsureHdrOut() %p [%d]\n", this, size))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::EnsureHdrOut() %p [%d]\n" , this, size); } } while (0); |
2242 | |
2243 | if (mDynamicOutputSize < size) { |
2244 | mDynamicOutputSize = size; |
2245 | mDynamicOutput = (uint8_t*)moz_xrealloc(mDynamicOutput, mDynamicOutputSize); |
2246 | } |
2247 | |
2248 | mHdrOut = mDynamicOutput; |
2249 | } |
2250 | |
2251 | namespace { |
2252 | |
2253 | class RemoveObserverRunnable : public Runnable { |
2254 | RefPtr<WebSocketChannel> mChannel; |
2255 | |
2256 | public: |
2257 | explicit RemoveObserverRunnable(WebSocketChannel* aChannel) |
2258 | : Runnable("net::RemoveObserverRunnable"), mChannel(aChannel) {} |
2259 | |
2260 | NS_IMETHODvirtual nsresult Run() override { |
2261 | nsCOMPtr<nsIObserverService> observerService = |
2262 | mozilla::services::GetObserverService(); |
2263 | if (!observerService) { |
2264 | NS_WARNING("failed to get observer service")NS_DebugBreak(NS_DEBUG_WARNING, "failed to get observer service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2264); |
2265 | return NS_OK; |
2266 | } |
2267 | |
2268 | observerService->RemoveObserver(mChannel, NS_NETWORK_LINK_TOPIC"network:link-status-changed"); |
2269 | return NS_OK; |
2270 | } |
2271 | }; |
2272 | |
2273 | } // namespace |
2274 | |
2275 | void WebSocketChannel::CleanupConnection() { |
2276 | // normally this should be called on socket thread, but it may be called |
2277 | // on MainThread |
2278 | |
2279 | LOG(("WebSocketChannel::CleanupConnection() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CleanupConnection() %p" , this); } } while (0); |
2280 | // This needs to run on the IOThread so we don't need to lock a bunch of these |
2281 | if (!mIOThread->IsOnCurrentThread()) { |
2282 | mIOThread->Dispatch( |
2283 | NewRunnableMethod("net::WebSocketChannel::CleanupConnection", this, |
2284 | &WebSocketChannel::CleanupConnection), |
2285 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2286 | return; |
2287 | } |
2288 | |
2289 | if (mLingeringCloseTimer) { |
2290 | mLingeringCloseTimer->Cancel(); |
2291 | mLingeringCloseTimer = nullptr; |
2292 | } |
2293 | |
2294 | if (mSocketIn) { |
2295 | if (mDataStarted) { |
2296 | mSocketIn->AsyncWait(nullptr, 0, 0, nullptr); |
2297 | } |
2298 | mSocketIn = nullptr; |
2299 | } |
2300 | |
2301 | if (mSocketOut) { |
2302 | mSocketOut->AsyncWait(nullptr, 0, 0, nullptr); |
2303 | mSocketOut = nullptr; |
2304 | } |
2305 | |
2306 | if (mTransport) { |
2307 | mTransport->SetSecurityCallbacks(nullptr); |
2308 | mTransport->SetEventSink(nullptr, nullptr); |
2309 | mTransport->Close(NS_BASE_STREAM_CLOSED); |
2310 | mTransport = nullptr; |
2311 | } |
2312 | |
2313 | if (mConnection) { |
2314 | mConnection->Close(); |
2315 | mConnection = nullptr; |
2316 | } |
2317 | |
2318 | if (mConnectionLogService && !mPrivateBrowsing) { |
2319 | mConnectionLogService->RemoveHost(mHost, mSerial); |
2320 | } |
2321 | |
2322 | // The observer has to be removed on the main-thread. |
2323 | NS_DispatchToMainThread(new RemoveObserverRunnable(this)); |
2324 | |
2325 | DecrementSessionCount(); |
2326 | } |
2327 | |
2328 | void WebSocketChannel::StopSession(nsresult reason) { |
2329 | LOG(("WebSocketChannel::StopSession() %p [%" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0) |
2330 | static_cast<uint32_t>(reason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0); |
2331 | |
2332 | { |
2333 | MutexAutoLock lock(mMutex); |
2334 | if (mStopped) { |
2335 | return; |
2336 | } |
2337 | mStopped = true; |
2338 | } |
2339 | |
2340 | DoStopSession(reason); |
2341 | } |
2342 | |
2343 | void WebSocketChannel::DoStopSession(nsresult reason) { |
2344 | LOG(("WebSocketChannel::DoStopSession() %p [%" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0) |
2345 | static_cast<uint32_t>(reason)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession() %p [%" "x" "]\n", this, static_cast<uint32_t>(reason)); } } while (0); |
2346 | |
2347 | // normally this should be called on socket thread, but it is ok to call it |
2348 | // from OnStartRequest before the socket thread machine has gotten underway. |
2349 | // If mDataStarted is false, this is called on MainThread for Close(). |
2350 | // Otherwise it should be called on the IO thread |
2351 | |
2352 | MOZ_ASSERT(mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")" ); do { *((volatile int*)__null) = 2352; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2353 | MOZ_ASSERT(mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread() || mTCPClosed || ! mDataStarted)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted" ")"); do { *((volatile int*)__null) = 2353; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2354 | |
2355 | if (!mOpenedHttpChannel) { |
2356 | // The HTTP channel information will never be used in this case |
2357 | NS_ReleaseOnMainThread("WebSocketChannel::mChannel", mChannel.forget()); |
2358 | NS_ReleaseOnMainThread("WebSocketChannel::mHttpChannel", |
2359 | mHttpChannel.forget()); |
2360 | NS_ReleaseOnMainThread("WebSocketChannel::mLoadGroup", mLoadGroup.forget()); |
2361 | NS_ReleaseOnMainThread("WebSocketChannel::mCallbacks", mCallbacks.forget()); |
2362 | } |
2363 | |
2364 | if (mCloseTimer) { |
2365 | mCloseTimer->Cancel(); |
2366 | mCloseTimer = nullptr; |
2367 | } |
2368 | |
2369 | // mOpenTimer must be null if mDataStarted is true and we're not on MainThread |
2370 | if (mOpenTimer) { |
2371 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2371; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2372 | mOpenTimer->Cancel(); |
2373 | mOpenTimer = nullptr; |
2374 | } |
2375 | |
2376 | { |
2377 | MutexAutoLock lock(mMutex); |
2378 | if (mReconnectDelayTimer) { |
2379 | mReconnectDelayTimer->Cancel(); |
2380 | NS_ReleaseOnMainThread("WebSocketChannel::mMutex", |
2381 | mReconnectDelayTimer.forget()); |
2382 | } |
2383 | } |
2384 | |
2385 | if (mPingTimer) { |
2386 | mPingTimer->Cancel(); |
2387 | mPingTimer = nullptr; |
2388 | } |
2389 | |
2390 | if (!mTCPClosed && mDataStarted) { |
2391 | if (mSocketIn) { |
2392 | // Drain, within reason, this socket. if we leave any data |
2393 | // unconsumed (including the tcp fin) a RST will be generated |
2394 | // The right thing to do here is shutdown(SHUT_WR) and then wait |
2395 | // a little while to see if any data comes in.. but there is no |
2396 | // reason to delay things for that when the websocket handshake |
2397 | // is supposed to guarantee a quiet connection except for that fin. |
2398 | |
2399 | char buffer[512]; |
2400 | uint32_t count = 0; |
2401 | uint32_t total = 0; |
2402 | nsresult rv; |
2403 | do { |
2404 | total += count; |
2405 | rv = mSocketIn->Read(buffer, 512, &count); |
2406 | if (rv != NS_BASE_STREAM_WOULD_BLOCK && (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || count == 0)) { |
2407 | mTCPClosed = true; |
2408 | } |
2409 | } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && count > 0 && total < 32000); |
2410 | } else if (mConnection) { |
2411 | mConnection->DrainSocketData(); |
2412 | } |
2413 | } |
2414 | |
2415 | int32_t sessionCount = kLingeringCloseThreshold; |
2416 | nsWSAdmissionManager::GetSessionCount(sessionCount); |
2417 | |
2418 | if (!mTCPClosed && (mTransport || mConnection) && |
2419 | sessionCount < kLingeringCloseThreshold) { |
2420 | // 7.1.1 says that the client SHOULD wait for the server to close the TCP |
2421 | // connection. This is so we can reuse port numbers before 2 MSL expires, |
2422 | // which is not really as much of a concern for us as the amount of state |
2423 | // that might be accrued by keeping this channel object around waiting for |
2424 | // the server. We handle the SHOULD by waiting a short time in the common |
2425 | // case, but not waiting in the case of high concurrency. |
2426 | // |
2427 | // Normally this will be taken care of in AbortSession() after mTCPClosed |
2428 | // is set when the server close arrives without waiting for the timeout to |
2429 | // expire. |
2430 | |
2431 | LOG(("WebSocketChannel::DoStopSession: Wait for Server TCP close"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStopSession: Wait for Server TCP close" ); } } while (0); |
2432 | |
2433 | nsresult rv; |
2434 | rv = NS_NewTimerWithCallback(getter_AddRefs(mLingeringCloseTimer), this, |
2435 | kLingeringCloseTimeout, |
2436 | nsITimer::TYPE_ONE_SHOT); |
2437 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CleanupConnection(); |
2438 | } else { |
2439 | CleanupConnection(); |
2440 | } |
2441 | |
2442 | { |
2443 | MutexAutoLock lock(mMutex); |
2444 | if (mCancelable) { |
2445 | mCancelable->Cancel(NS_ERROR_UNEXPECTED); |
2446 | mCancelable = nullptr; |
2447 | } |
2448 | } |
2449 | |
2450 | { |
2451 | MutexAutoLock lock(mCompressorMutex); |
2452 | mPMCECompressor = nullptr; |
2453 | } |
2454 | if (!mCalledOnStop) { |
2455 | mCalledOnStop = true; |
2456 | |
2457 | nsWSAdmissionManager::OnStopSession(this, reason); |
2458 | |
2459 | RefPtr<CallOnStop> runnable = new CallOnStop(this, reason); |
2460 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
2461 | target->Dispatch(runnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2462 | } |
2463 | } |
2464 | } |
2465 | |
2466 | // Called from MainThread, and called from IOThread in |
2467 | // PrimeNewOutgoingMessage |
2468 | void WebSocketChannel::AbortSession(nsresult reason) { |
2469 | LOG(("WebSocketChannel::AbortSession() %p [reason %" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %" "x" "] stopped = %d\n", this, static_cast<uint32_t>(reason ), !!mStopped); } } while (0) |
2470 | "] stopped = %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %" "x" "] stopped = %d\n", this, static_cast<uint32_t>(reason ), !!mStopped); } } while (0) |
2471 | this, static_cast<uint32_t>(reason), !!mStopped))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AbortSession() %p [reason %" "x" "] stopped = %d\n", this, static_cast<uint32_t>(reason ), !!mStopped); } } while (0); |
2472 | |
2473 | MOZ_ASSERT(NS_FAILED(reason), "reason must be a failure!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))" " (" "reason must be a failure!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))" ") (" "reason must be a failure!" ")"); do { *((volatile int *)__null) = 2473; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2474 | |
2475 | // normally this should be called on socket thread, but it is ok to call it |
2476 | // from the main thread before StartWebsocketData() has completed |
2477 | MOZ_ASSERT(mIOThread->IsOnCurrentThread() || !mDataStarted)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread() || !mDataStarted)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mIOThread->IsOnCurrentThread() || !mDataStarted)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mIOThread->IsOnCurrentThread() || !mDataStarted" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || !mDataStarted" ")"); do { *((volatile int*)__null) = 2477; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2478 | |
2479 | // When we are failing we need to close the TCP connection immediately |
2480 | // as per 7.1.1 |
2481 | mTCPClosed = true; |
2482 | |
2483 | if (mLingeringCloseTimer) { |
2484 | MOZ_ASSERT(mStopped, "Lingering without Stop")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped" " (" "Lingering without Stop" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") (" "Lingering without Stop" ")"); do { *((volatile int*)__null) = 2484; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2485 | LOG(("WebSocketChannel:: Cleanup connection based on TCP Close"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Cleanup connection based on TCP Close" ); } } while (0); |
2486 | CleanupConnection(); |
2487 | return; |
2488 | } |
2489 | |
2490 | { |
2491 | MutexAutoLock lock(mMutex); |
2492 | if (mStopped) { |
2493 | return; |
2494 | } |
2495 | |
2496 | if ((mTransport || mConnection) && reason != NS_BASE_STREAM_CLOSED && |
2497 | !mRequestedClose && !mClientClosed && !mServerClosed && mDataStarted) { |
2498 | mRequestedClose = true; |
2499 | mStopOnClose = reason; |
2500 | mIOThread->Dispatch( |
2501 | new OutboundEnqueuer(this, |
2502 | new OutboundMessage(kMsgTypeFin, VoidCString())), |
2503 | nsIEventTarget::DISPATCH_NORMAL); |
2504 | return; |
2505 | } |
2506 | |
2507 | mStopped = true; |
2508 | } |
2509 | |
2510 | DoStopSession(reason); |
2511 | } |
2512 | |
2513 | // ReleaseSession is called on orderly shutdown |
2514 | void WebSocketChannel::ReleaseSession() { |
2515 | LOG(("WebSocketChannel::ReleaseSession() %p stopped = %d\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReleaseSession() %p stopped = %d\n" , this, !!mStopped); } } while (0) |
2516 | !!mStopped))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReleaseSession() %p stopped = %d\n" , this, !!mStopped); } } while (0); |
2517 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 2517; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2518 | |
2519 | StopSession(NS_OK); |
2520 | } |
2521 | |
2522 | void WebSocketChannel::IncrementSessionCount() { |
2523 | if (!mIncrementedSessionCount) { |
2524 | nsWSAdmissionManager::IncrementSessionCount(); |
2525 | mIncrementedSessionCount = true; |
2526 | } |
2527 | } |
2528 | |
2529 | void WebSocketChannel::DecrementSessionCount() { |
2530 | // Make sure we decrement session count only once, and only if we incremented |
2531 | // it. This code is thread-safe: sWebSocketAdmissions->DecrementSessionCount |
2532 | // is atomic, and mIncrementedSessionCount/mDecrementedSessionCount are set at |
2533 | // times when they'll never be a race condition for checking/setting them. |
2534 | if (mIncrementedSessionCount && !mDecrementedSessionCount) { |
2535 | nsWSAdmissionManager::DecrementSessionCount(); |
2536 | mDecrementedSessionCount = true; |
2537 | } |
2538 | } |
2539 | |
2540 | namespace { |
2541 | enum ExtensionParseMode { eParseServerSide, eParseClientSide }; |
2542 | } |
2543 | |
2544 | static nsresult ParseWebSocketExtension(const nsACString& aExtension, |
2545 | ExtensionParseMode aMode, |
2546 | bool& aClientNoContextTakeover, |
2547 | bool& aServerNoContextTakeover, |
2548 | int32_t& aClientMaxWindowBits, |
2549 | int32_t& aServerMaxWindowBits) { |
2550 | nsCCharSeparatedTokenizer tokens(aExtension, ';'); |
2551 | |
2552 | if (!tokens.hasMoreTokens() || |
2553 | !tokens.nextToken().EqualsLiteral("permessage-deflate")) { |
2554 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0) |
2555 | ("WebSocketChannel::ParseWebSocketExtension: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0) |
2556 | "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0) |
2557 | PromiseFlatCString(aExtension).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: " "HTTP Sec-WebSocket-Extensions negotiated unknown value %s\n" , TPromiseFlatString<char>(aExtension).get()); } } while (0); |
2558 | return NS_ERROR_ILLEGAL_VALUE; |
2559 | } |
2560 | |
2561 | aClientNoContextTakeover = aServerNoContextTakeover = false; |
2562 | aClientMaxWindowBits = aServerMaxWindowBits = -1; |
2563 | |
2564 | while (tokens.hasMoreTokens()) { |
2565 | auto token = tokens.nextToken(); |
2566 | |
2567 | int32_t nameEnd, valueStart; |
2568 | int32_t delimPos = token.FindChar('='); |
2569 | if (delimPos == kNotFound) { |
2570 | nameEnd = token.Length(); |
2571 | valueStart = token.Length(); |
2572 | } else { |
2573 | nameEnd = delimPos; |
2574 | valueStart = delimPos + 1; |
2575 | } |
2576 | |
2577 | auto paramName = Substring(token, 0, nameEnd); |
2578 | auto paramValue = Substring(token, valueStart); |
2579 | |
2580 | if (paramName.EqualsLiteral("client_no_context_takeover")) { |
2581 | if (!paramValue.IsEmpty()) { |
2582 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2583 | ("WebSocketChannel::ParseWebSocketExtension: parameter "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2584 | "client_no_context_takeover must not have value, found %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2585 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "client_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0); |
2586 | return NS_ERROR_ILLEGAL_VALUE; |
2587 | } |
2588 | if (aClientNoContextTakeover) { |
2589 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_no_context_takeover\n"); } } while (0) |
2590 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_no_context_takeover\n"); } } while (0) |
2591 | "parameters client_no_context_takeover\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_no_context_takeover\n"); } } while (0); |
2592 | return NS_ERROR_ILLEGAL_VALUE; |
2593 | } |
2594 | aClientNoContextTakeover = true; |
2595 | } else if (paramName.EqualsLiteral("server_no_context_takeover")) { |
2596 | if (!paramValue.IsEmpty()) { |
2597 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2598 | ("WebSocketChannel::ParseWebSocketExtension: parameter "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2599 | "server_no_context_takeover must not have value, found %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0) |
2600 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: parameter " "server_no_context_takeover must not have value, found %s\n" , TPromiseFlatString<char>(paramValue).get()); } } while (0); |
2601 | return NS_ERROR_ILLEGAL_VALUE; |
2602 | } |
2603 | if (aServerNoContextTakeover) { |
2604 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_no_context_takeover\n"); } } while (0) |
2605 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_no_context_takeover\n"); } } while (0) |
2606 | "parameters server_no_context_takeover\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_no_context_takeover\n"); } } while (0); |
2607 | return NS_ERROR_ILLEGAL_VALUE; |
2608 | } |
2609 | aServerNoContextTakeover = true; |
2610 | } else if (paramName.EqualsLiteral("client_max_window_bits")) { |
2611 | if (aClientMaxWindowBits != -1) { |
2612 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_max_window_bits\n"); } } while (0) |
2613 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_max_window_bits\n"); } } while (0) |
2614 | "parameters client_max_window_bits\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters client_max_window_bits\n"); } } while (0); |
2615 | return NS_ERROR_ILLEGAL_VALUE; |
2616 | } |
2617 | |
2618 | if (aMode == eParseServerSide && paramValue.IsEmpty()) { |
2619 | // Use -2 to indicate that "client_max_window_bits" has been parsed, |
2620 | // but had no value. |
2621 | aClientMaxWindowBits = -2; |
2622 | } else { |
2623 | nsresult errcode; |
2624 | aClientMaxWindowBits = |
2625 | PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode); |
2626 | if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aClientMaxWindowBits < 8 || |
2627 | aClientMaxWindowBits > 15) { |
2628 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2629 | ("WebSocketChannel::ParseWebSocketExtension: found invalid "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2630 | "parameter client_max_window_bits %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2631 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter client_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0); |
2632 | return NS_ERROR_ILLEGAL_VALUE; |
2633 | } |
2634 | } |
2635 | } else if (paramName.EqualsLiteral("server_max_window_bits")) { |
2636 | if (aServerMaxWindowBits != -1) { |
2637 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_max_window_bits\n"); } } while (0) |
2638 | ("WebSocketChannel::ParseWebSocketExtension: found multiple "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_max_window_bits\n"); } } while (0) |
2639 | "parameters server_max_window_bits\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found multiple " "parameters server_max_window_bits\n"); } } while (0); |
2640 | return NS_ERROR_ILLEGAL_VALUE; |
2641 | } |
2642 | |
2643 | nsresult errcode; |
2644 | aServerMaxWindowBits = PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode); |
2645 | if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aServerMaxWindowBits < 8 || |
2646 | aServerMaxWindowBits > 15) { |
2647 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2648 | ("WebSocketChannel::ParseWebSocketExtension: found invalid "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2649 | "parameter server_max_window_bits %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0) |
2650 | PromiseFlatCString(paramValue).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found invalid " "parameter server_max_window_bits %s\n", TPromiseFlatString< char>(paramValue).get()); } } while (0); |
2651 | return NS_ERROR_ILLEGAL_VALUE; |
2652 | } |
2653 | } else { |
2654 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0) |
2655 | ("WebSocketChannel::ParseWebSocketExtension: found unknown "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0) |
2656 | "parameter %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0) |
2657 | PromiseFlatCString(paramName).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ParseWebSocketExtension: found unknown " "parameter %s\n", TPromiseFlatString<char>(paramName). get()); } } while (0); |
2658 | return NS_ERROR_ILLEGAL_VALUE; |
2659 | } |
2660 | } |
2661 | |
2662 | if (aClientMaxWindowBits == -2) { |
2663 | aClientMaxWindowBits = -1; |
2664 | } |
2665 | |
2666 | return NS_OK; |
2667 | } |
2668 | |
2669 | nsresult WebSocketChannel::HandleExtensions() { |
2670 | LOG(("WebSocketChannel::HandleExtensions() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions() %p\n" , this); } } while (0); |
2671 | |
2672 | nsresult rv; |
2673 | nsAutoCString extensions; |
2674 | |
2675 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2675; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2676 | |
2677 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Extensions"_ns, |
Value stored to 'rv' is never read | |
2678 | extensions); |
2679 | extensions.CompressWhitespace(); |
2680 | if (extensions.IsEmpty()) { |
2681 | return NS_OK; |
2682 | } |
2683 | |
2684 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0) |
2685 | ("WebSocketChannel::HandleExtensions: received "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0) |
2686 | "Sec-WebSocket-Extensions header: %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0) |
2687 | extensions.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: received " "Sec-WebSocket-Extensions header: %s\n", extensions.get()); } } while (0); |
2688 | |
2689 | bool clientNoContextTakeover; |
2690 | bool serverNoContextTakeover; |
2691 | int32_t clientMaxWindowBits; |
2692 | int32_t serverMaxWindowBits; |
2693 | |
2694 | rv = ParseWebSocketExtension(extensions, eParseClientSide, |
2695 | clientNoContextTakeover, serverNoContextTakeover, |
2696 | clientMaxWindowBits, serverMaxWindowBits); |
2697 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2698 | AbortSession(rv); |
2699 | return rv; |
2700 | } |
2701 | |
2702 | if (clientMaxWindowBits == -1) { |
2703 | clientMaxWindowBits = 15; |
2704 | } |
2705 | if (serverMaxWindowBits == -1) { |
2706 | serverMaxWindowBits = 15; |
2707 | } |
2708 | |
2709 | MutexAutoLock lock(mCompressorMutex); |
2710 | mPMCECompressor = MakeUnique<PMCECompression>( |
2711 | clientNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits); |
2712 | if (mPMCECompressor->Active()) { |
2713 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2714 | ("WebSocketChannel::HandleExtensions: PMCE negotiated, %susing "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2715 | "context takeover, clientMaxWindowBits=%d, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2716 | "serverMaxWindowBits=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2717 | clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2718 | serverMaxWindowBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0); |
2719 | |
2720 | mNegotiatedExtensions = "permessage-deflate"; |
2721 | } else { |
2722 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE " "compression object\n"); } } while (0) |
2723 | ("WebSocketChannel::HandleExtensions: Cannot init PMCE "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE " "compression object\n"); } } while (0) |
2724 | "compression object\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::HandleExtensions: Cannot init PMCE " "compression object\n"); } } while (0); |
2725 | mPMCECompressor = nullptr; |
2726 | AbortSession(NS_ERROR_UNEXPECTED); |
2727 | return NS_ERROR_UNEXPECTED; |
2728 | } |
2729 | |
2730 | return NS_OK; |
2731 | } |
2732 | |
2733 | void ProcessServerWebSocketExtensions(const nsACString& aExtensions, |
2734 | nsACString& aNegotiatedExtensions) { |
2735 | aNegotiatedExtensions.Truncate(); |
2736 | |
2737 | for (const auto& ext : |
2738 | nsCCharSeparatedTokenizer(aExtensions, ',').ToRange()) { |
2739 | bool clientNoContextTakeover; |
2740 | bool serverNoContextTakeover; |
2741 | int32_t clientMaxWindowBits; |
2742 | int32_t serverMaxWindowBits; |
2743 | |
2744 | nsresult rv = ParseWebSocketExtension( |
2745 | ext, eParseServerSide, clientNoContextTakeover, serverNoContextTakeover, |
2746 | clientMaxWindowBits, serverMaxWindowBits); |
2747 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2748 | // Ignore extensions that we can't parse |
2749 | continue; |
2750 | } |
2751 | |
2752 | aNegotiatedExtensions.AssignLiteral("permessage-deflate"); |
2753 | if (clientNoContextTakeover) { |
2754 | aNegotiatedExtensions.AppendLiteral(";client_no_context_takeover"); |
2755 | } |
2756 | if (serverNoContextTakeover) { |
2757 | aNegotiatedExtensions.AppendLiteral(";server_no_context_takeover"); |
2758 | } |
2759 | if (clientMaxWindowBits != -1) { |
2760 | aNegotiatedExtensions.AppendLiteral(";client_max_window_bits="); |
2761 | aNegotiatedExtensions.AppendInt(clientMaxWindowBits); |
2762 | } |
2763 | if (serverMaxWindowBits != -1) { |
2764 | aNegotiatedExtensions.AppendLiteral(";server_max_window_bits="); |
2765 | aNegotiatedExtensions.AppendInt(serverMaxWindowBits); |
2766 | } |
2767 | |
2768 | return; |
2769 | } |
2770 | } |
2771 | |
2772 | nsresult CalculateWebSocketHashedSecret(const nsACString& aKey, |
2773 | nsACString& aHash) { |
2774 | nsresult rv; |
2775 | nsCString key = aKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_ns; |
2776 | nsCOMPtr<nsICryptoHash> hasher = |
2777 | do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv); |
2778 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2778); return rv; } } while (false); |
2779 | rv = hasher->Init(nsICryptoHash::SHA1); |
2780 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2780); return rv; } } while (false); |
2781 | rv = hasher->Update((const uint8_t*)key.BeginWriting(), key.Length()); |
2782 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2782); return rv; } } while (false); |
2783 | return hasher->Finish(true, aHash); |
2784 | } |
2785 | |
2786 | nsresult WebSocketChannel::SetupRequest() { |
2787 | LOG(("WebSocketChannel::SetupRequest() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest() %p\n" , this); } } while (0); |
2788 | |
2789 | nsresult rv; |
2790 | |
2791 | if (mLoadGroup) { |
2792 | rv = mHttpChannel->SetLoadGroup(mLoadGroup); |
2793 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2793); return rv; } } while (false); |
2794 | } |
2795 | |
2796 | rv = mHttpChannel->SetLoadFlags( |
2797 | nsIRequest::LOAD_BACKGROUND | nsIRequest::INHIBIT_CACHING | |
2798 | nsIRequest::LOAD_BYPASS_CACHE | nsIChannel::LOAD_BYPASS_SERVICE_WORKER); |
2799 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2799); return rv; } } while (false); |
2800 | |
2801 | // we never let websockets be blocked by head CSS/JS loads to avoid |
2802 | // potential deadlock where server generation of CSS/JS requires |
2803 | // an XHR signal. |
2804 | nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel)); |
2805 | if (cos) { |
2806 | cos->AddClassFlags(nsIClassOfService::Unblocked); |
2807 | } |
2808 | |
2809 | // draft-ietf-hybi-thewebsocketprotocol-07 illustrates Upgrade: websocket |
2810 | // in lower case, so go with that. It is technically case insensitive. |
2811 | rv = mChannel->HTTPUpgrade("websocket"_ns, this); |
2812 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2812); return rv; } } while (false); |
2813 | |
2814 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Version"_ns, |
2815 | nsLiteralCString(SEC_WEBSOCKET_VERSION"13"), |
2816 | false); |
2817 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2818 | |
2819 | if (!mOrigin.IsEmpty()) { |
2820 | rv = mHttpChannel->SetRequestHeader("Origin"_ns, mOrigin, false); |
2821 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2821; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2822 | } |
2823 | |
2824 | if (!mProtocol.IsEmpty()) { |
2825 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Protocol"_ns, mProtocol, |
2826 | true); |
2827 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2827); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2827; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2828 | } |
2829 | |
2830 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Extensions"_ns, |
2831 | "permessage-deflate"_ns, false); |
2832 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2832; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2833 | |
2834 | uint8_t* secKey; |
2835 | nsAutoCString secKeyString; |
2836 | |
2837 | rv = mRandomGenerator->GenerateRandomBytes(16, &secKey); |
2838 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2838); return rv; } } while (false); |
2839 | rv = Base64Encode(reinterpret_cast<const char*>(secKey), 16, secKeyString); |
2840 | free(secKey); |
2841 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2842 | return rv; |
2843 | } |
2844 | |
2845 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Key"_ns, secKeyString, |
2846 | false); |
2847 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2848 | LOG(("WebSocketChannel::SetupRequest: client key %s\n", secKeyString.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: client key %s\n" , secKeyString.get()); } } while (0); |
2849 | |
2850 | // prepare the value we expect to see in |
2851 | // the sec-websocket-accept response header |
2852 | rv = CalculateWebSocketHashedSecret(secKeyString, mHashedSecret); |
2853 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2853); return rv; } } while (false); |
2854 | LOG(("WebSocketChannel::SetupRequest: expected server key %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: expected server key %s\n" , mHashedSecret.get()); } } while (0) |
2855 | mHashedSecret.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SetupRequest: expected server key %s\n" , mHashedSecret.get()); } } while (0); |
2856 | |
2857 | mHttpChannelId = mHttpChannel->ChannelId(); |
2858 | |
2859 | return NS_OK; |
2860 | } |
2861 | |
2862 | nsresult WebSocketChannel::DoAdmissionDNS() { |
2863 | nsresult rv; |
2864 | |
2865 | nsCString hostName; |
2866 | rv = mURI->GetHost(hostName); |
2867 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2867); return rv; } } while (false); |
2868 | mAddress = hostName; |
2869 | nsCString path; |
2870 | rv = mURI->GetFilePath(path); |
2871 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2871); return rv; } } while (false); |
2872 | mPath = path; |
2873 | rv = mURI->GetPort(&mPort); |
2874 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2874); return rv; } } while (false); |
2875 | if (mPort == -1) mPort = (mEncrypted ? kDefaultWSSPort : kDefaultWSPort); |
2876 | nsCOMPtr<nsIDNSService> dns; |
2877 | dns = mozilla::components::DNS::Service(&rv); |
2878 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2878); return rv; } } while (false); |
2879 | nsCOMPtr<nsIEventTarget> main = GetMainThreadSerialEventTarget(); |
2880 | nsCOMPtr<nsICancelable> cancelable; |
2881 | rv = dns->AsyncResolveNative(hostName, nsIDNSService::RESOLVE_TYPE_DEFAULT, |
2882 | nsIDNSService::RESOLVE_DEFAULT_FLAGS, nullptr, |
2883 | this, main, mLoadInfo->GetOriginAttributes(), |
2884 | getter_AddRefs(cancelable)); |
2885 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2886 | return rv; |
2887 | } |
2888 | |
2889 | MutexAutoLock lock(mMutex); |
2890 | MOZ_ASSERT(!mCancelable)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ")"); do { *((volatile int*)__null) = 2890; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2891 | mCancelable = std::move(cancelable); |
2892 | return rv; |
2893 | } |
2894 | |
2895 | nsresult WebSocketChannel::ApplyForAdmission() { |
2896 | LOG(("WebSocketChannel::ApplyForAdmission() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission() %p\n" , this); } } while (0); |
2897 | |
2898 | // Websockets has a policy of 1 session at a time being allowed in the |
2899 | // CONNECTING state per server IP address (not hostname) |
2900 | |
2901 | // Check to see if a proxy is being used before making DNS call |
2902 | nsCOMPtr<nsIProtocolProxyService> pps; |
2903 | pps = mozilla::components::ProtocolProxy::Service(); |
2904 | |
2905 | if (!pps) { |
2906 | // go straight to DNS |
2907 | // expect the callback in ::OnLookupComplete |
2908 | LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n" ); } } while (0) |
2909 | "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ApplyForAdmission: checking for concurrent open\n" ); } } while (0); |
2910 | return DoAdmissionDNS(); |
2911 | } |
2912 | |
2913 | nsresult rv; |
2914 | nsCOMPtr<nsICancelable> cancelable; |
2915 | rv = pps->AsyncResolve( |
2916 | mHttpChannel, |
2917 | nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY | |
2918 | nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY | |
2919 | nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL, |
2920 | this, nullptr, getter_AddRefs(cancelable)); |
2921 | |
2922 | MutexAutoLock lock(mMutex); |
2923 | MOZ_ASSERT(!mCancelable)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mCancelable))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ")"); do { *((volatile int*)__null) = 2923; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2924 | mCancelable = std::move(cancelable); |
2925 | return rv; |
2926 | } |
2927 | |
2928 | // Called after both OnStartRequest and OnTransportAvailable have |
2929 | // executed. This essentially ends the handshake and starts the websockets |
2930 | // protocol state machine. |
2931 | nsresult WebSocketChannel::CallStartWebsocketData() { |
2932 | LOG(("WebSocketChannel::CallStartWebsocketData() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::CallStartWebsocketData() %p" , this); } } while (0); |
2933 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2933; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2934 | |
2935 | if (mOpenTimer) { |
2936 | mOpenTimer->Cancel(); |
2937 | mOpenTimer = nullptr; |
2938 | } |
2939 | |
2940 | nsCOMPtr<nsIEventTarget> target = GetTargetThread(); |
2941 | if (target && !target->IsOnCurrentThread()) { |
2942 | return target->Dispatch( |
2943 | NewRunnableMethod("net::WebSocketChannel::StartWebsocketData", this, |
2944 | &WebSocketChannel::StartWebsocketData), |
2945 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2946 | } |
2947 | |
2948 | return StartWebsocketData(); |
2949 | } |
2950 | |
2951 | nsresult WebSocketChannel::StartWebsocketData() { |
2952 | { |
2953 | MutexAutoLock lock(mMutex); |
2954 | LOG(("WebSocketChannel::StartWebsocketData() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData() %p" , this); } } while (0); |
2955 | MOZ_ASSERT(!mDataStarted, "StartWebsocketData twice")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDataStarted)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDataStarted))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDataStarted" " (" "StartWebsocketData twice" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDataStarted" ") (" "StartWebsocketData twice" ")"); do { *((volatile int* )__null) = 2955; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
2956 | |
2957 | if (mStopped) { |
2958 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not " "starting data"); } } while (0) |
2959 | ("WebSocketChannel::StartWebsocketData channel already closed, not "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not " "starting data"); } } while (0) |
2960 | "starting data"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData channel already closed, not " "starting data"); } } while (0); |
2961 | return NS_ERROR_NOT_AVAILABLE; |
2962 | } |
2963 | } |
2964 | |
2965 | RefPtr<WebSocketChannel> self = this; |
2966 | mIOThread->Dispatch(NS_NewRunnableFunction( |
2967 | "WebSocketChannel::StartWebsocketData", [self{std::move(self)}] { |
2968 | LOG(("WebSocketChannel::DoStartWebsocketData() %p", self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoStartWebsocketData() %p" , self.get()); } } while (0); |
2969 | |
2970 | NS_DispatchToMainThread( |
2971 | NewRunnableMethod("net::WebSocketChannel::NotifyOnStart", self, |
2972 | &WebSocketChannel::NotifyOnStart), |
2973 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2974 | |
2975 | nsresult rv = self->mConnection ? self->mConnection->StartReading() |
2976 | : self->mSocketIn->AsyncWait( |
2977 | self, 0, 0, self->mIOThread); |
2978 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2979 | self->AbortSession(rv); |
2980 | } |
2981 | |
2982 | if (self->mPingInterval) { |
2983 | rv = self->StartPinging(); |
2984 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2985 | LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0) |
2986 | "WebSocketChannel::StartWebsocketData Could not start pinging, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0) |
2987 | "rv=0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0) |
2988 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartWebsocketData Could not start pinging, " "rv=0x%08" "x", static_cast<uint32_t>(rv)); } } while ( 0); |
2989 | self->AbortSession(rv); |
2990 | } |
2991 | } |
2992 | })); |
2993 | |
2994 | return NS_OK; |
2995 | } |
2996 | |
2997 | void WebSocketChannel::NotifyOnStart() { |
2998 | LOG(("WebSocketChannel::NotifyOnStart Notifying Listener %p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0) |
2999 | mListenerMT ? mListenerMT->mListener.get() : nullptr))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0); |
3000 | mDataStarted = true; |
3001 | if (mListenerMT) { |
3002 | nsresult rv = mListenerMT->mListener->OnStart(mListenerMT->mContext); |
3003 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3004 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
3005 | ("WebSocketChannel::NotifyOnStart "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
3006 | "mListenerMT->mListener->OnStart() failed with error 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0) |
3007 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::NotifyOnStart " "mListenerMT->mListener->OnStart() failed with error 0x%08" "x", static_cast<uint32_t>(rv)); } } while (0); |
3008 | } |
3009 | } |
3010 | } |
3011 | |
3012 | nsresult WebSocketChannel::StartPinging() { |
3013 | LOG(("WebSocketChannel::StartPinging() %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::StartPinging() %p" , this); } } while (0); |
3014 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3014; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3015 | MOZ_ASSERT(mPingInterval)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPingInterval)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mPingInterval))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mPingInterval", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval" ")"); do { *((volatile int*)__null) = 3015; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3016 | MOZ_ASSERT(!mPingTimer)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mPingTimer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mPingTimer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mPingTimer", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPingTimer" ")"); do { *((volatile int*)__null) = 3016; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3017 | |
3018 | nsresult rv; |
3019 | rv = NS_NewTimerWithCallback(getter_AddRefs(mPingTimer), this, mPingInterval, |
3020 | nsITimer::TYPE_ONE_SHOT); |
3021 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3022 | LOG(("WebSocketChannel will generate ping after %d ms of receive silence\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel will generate ping after %d ms of receive silence\n" , (uint32_t)mPingInterval); } } while (0) |
3023 | (uint32_t)mPingInterval))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel will generate ping after %d ms of receive silence\n" , (uint32_t)mPingInterval); } } while (0); |
3024 | } else { |
3025 | NS_WARNING("unable to create ping timer. Carrying on.")NS_DebugBreak(NS_DEBUG_WARNING, "unable to create ping timer. Carrying on." , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3025); |
3026 | } |
3027 | |
3028 | return NS_OK; |
3029 | } |
3030 | |
3031 | void WebSocketChannel::ReportConnectionTelemetry(nsresult aStatusCode) { |
3032 | // 3 bits are used. high bit is for wss, middle bit for failed, |
3033 | // and low bit for proxy.. |
3034 | // 0 - 7 : ws-ok-plain, ws-ok-proxy, ws-failed-plain, ws-failed-proxy, |
3035 | // wss-ok-plain, wss-ok-proxy, wss-failed-plain, wss-failed-proxy |
3036 | |
3037 | bool didProxy = false; |
3038 | |
3039 | nsCOMPtr<nsIProxyInfo> pi; |
3040 | nsCOMPtr<nsIProxiedChannel> pc = do_QueryInterface(mChannel); |
3041 | if (pc) pc->GetProxyInfo(getter_AddRefs(pi)); |
3042 | if (pi) { |
3043 | nsAutoCString proxyType; |
3044 | pi->GetType(proxyType); |
3045 | if (!proxyType.IsEmpty() && !proxyType.EqualsLiteral("direct")) { |
3046 | didProxy = true; |
3047 | } |
3048 | } |
3049 | |
3050 | uint8_t value = |
3051 | (mEncrypted ? (1 << 2) : 0) | |
3052 | (!(mGotUpgradeOK && NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1) ))) ? (1 << 1) : 0) | |
3053 | (didProxy ? (1 << 0) : 0); |
3054 | |
3055 | LOG(("WebSocketChannel::ReportConnectionTelemetry() %p %d", this, value))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::ReportConnectionTelemetry() %p %d" , this, value); } } while (0); |
3056 | Telemetry::Accumulate(Telemetry::WEBSOCKETS_HANDSHAKE_TYPE, value); |
3057 | } |
3058 | |
3059 | // nsIDNSListener |
3060 | |
3061 | NS_IMETHODIMPnsresult |
3062 | WebSocketChannel::OnLookupComplete(nsICancelable* aRequest, |
3063 | nsIDNSRecord* aRecord, nsresult aStatus) { |
3064 | LOG(("WebSocketChannel::OnLookupComplete() %p [%p %p %" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete() %p [%p %p %" "x" "]\n", this, aRequest, aRecord, static_cast<uint32_t> (aStatus)); } } while (0) |
3065 | aRequest, aRecord, static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete() %p [%p %p %" "x" "]\n", this, aRequest, aRecord, static_cast<uint32_t> (aStatus)); } } while (0); |
3066 | |
3067 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3067; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3068 | |
3069 | { |
3070 | MutexAutoLock lock(mMutex); |
3071 | mCancelable = nullptr; |
3072 | } |
3073 | |
3074 | if (mStopped) { |
3075 | LOG(("WebSocketChannel::OnLookupComplete: Request Already Stopped\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: Request Already Stopped\n" ); } } while (0); |
3076 | return NS_OK; |
3077 | } |
3078 | |
3079 | // These failures are not fatal - we just use the hostname as the key |
3080 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
3081 | LOG(("WebSocketChannel::OnLookupComplete: No DNS Response\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: No DNS Response\n" ); } } while (0); |
3082 | |
3083 | // set host in case we got here without calling DoAdmissionDNS() |
3084 | mURI->GetHost(mAddress); |
3085 | } else { |
3086 | nsCOMPtr<nsIDNSAddrRecord> record = do_QueryInterface(aRecord); |
3087 | MOZ_ASSERT(record)do { static_assert( mozilla::detail::AssertionConditionType< decltype(record)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(record))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("record", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3087); AnnotateMozCrashReason("MOZ_ASSERT" "(" "record" ")" ); do { *((volatile int*)__null) = 3087; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3088 | nsresult rv = record->GetNextAddrAsString(mAddress); |
3089 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3090 | LOG(("WebSocketChannel::OnLookupComplete: Failed GetNextAddr\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnLookupComplete: Failed GetNextAddr\n" ); } } while (0); |
3091 | } |
3092 | } |
3093 | |
3094 | LOG(("WebSocket OnLookupComplete: Proceeding to ConditionallyConnect\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnLookupComplete: Proceeding to ConditionallyConnect\n" ); } } while (0); |
3095 | nsWSAdmissionManager::ConditionallyConnect(this); |
3096 | |
3097 | return NS_OK; |
3098 | } |
3099 | |
3100 | // nsIProtocolProxyCallback |
3101 | NS_IMETHODIMPnsresult |
3102 | WebSocketChannel::OnProxyAvailable(nsICancelable* aRequest, |
3103 | nsIChannel* aChannel, nsIProxyInfo* pi, |
3104 | nsresult status) { |
3105 | { |
3106 | MutexAutoLock lock(mMutex); |
3107 | MOZ_ASSERT(!mCancelable || (aRequest == mCancelable))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mCancelable || (aRequest == mCancelable))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mCancelable || (aRequest == mCancelable)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mCancelable || (aRequest == mCancelable)" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3107); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable || (aRequest == mCancelable)" ")"); do { *((volatile int*)__null) = 3107; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3108 | mCancelable = nullptr; |
3109 | } |
3110 | |
3111 | if (mStopped) { |
3112 | LOG(("WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n" , this); } } while (0) |
3113 | this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n" , this); } } while (0); |
3114 | return NS_OK; |
3115 | } |
3116 | |
3117 | nsAutoCString type; |
3118 | if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && pi && NS_SUCCEEDED(pi->GetType(type))((bool)(__builtin_expect(!!(!NS_FAILED_impl(pi->GetType(type ))), 1))) && |
3119 | !type.EqualsLiteral("direct")) { |
3120 | LOG(("WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n" , this); } } while (0) |
3121 | this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n" , this); } } while (0); |
3122 | // call DNS callback directly without DNS resolver |
3123 | OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); |
3124 | } else { |
3125 | LOG(("WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n" , this); } } while (0) |
3126 | this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable[%p] checking DNS resolution\n" , this); } } while (0); |
3127 | nsresult rv = DoAdmissionDNS(); |
3128 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3129 | LOG(("WebSocket OnProxyAvailable [%p] DNS lookup failed\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocket OnProxyAvailable [%p] DNS lookup failed\n" , this); } } while (0); |
3130 | // call DNS callback directly without DNS resolver |
3131 | OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); |
3132 | } |
3133 | } |
3134 | |
3135 | // notify listener of OnProxyAvailable |
3136 | LOG(("WebSocketChannel::OnProxyAvailable Notifying Listener %p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0) |
3137 | mListenerMT ? mListenerMT->mListener.get() : nullptr))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable Notifying Listener %p" , mListenerMT ? mListenerMT->mListener.get() : nullptr); } } while (0); |
3138 | nsresult rv; |
3139 | nsCOMPtr<nsIProtocolProxyCallback> ppc( |
3140 | do_QueryInterface(mListenerMT->mListener, &rv)); |
3141 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3142 | rv = ppc->OnProxyAvailable(aRequest, aChannel, pi, status); |
3143 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3144 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0) |
3145 | ("WebSocketChannel::OnProxyAvailable notify"do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0) |
3146 | " failed with error 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0) |
3147 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnProxyAvailable notify" " failed with error 0x%08" "x", static_cast<uint32_t>( rv)); } } while (0); |
3148 | } |
3149 | } |
3150 | |
3151 | return NS_OK; |
3152 | } |
3153 | |
3154 | // nsIInterfaceRequestor |
3155 | |
3156 | NS_IMETHODIMPnsresult |
3157 | WebSocketChannel::GetInterface(const nsIID& iid, void** result) { |
3158 | LOG(("WebSocketChannel::GetInterface() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GetInterface() %p\n" , this); } } while (0); |
3159 | |
3160 | if (iid.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::COMTypeInfo<nsIChannelEventSink, void >::kIID))) { |
3161 | return QueryInterface(iid, result); |
3162 | } |
3163 | |
3164 | if (mCallbacks) return mCallbacks->GetInterface(iid, result); |
3165 | |
3166 | return NS_ERROR_NO_INTERFACE; |
3167 | } |
3168 | |
3169 | // nsIChannelEventSink |
3170 | |
3171 | NS_IMETHODIMPnsresult |
3172 | WebSocketChannel::AsyncOnChannelRedirect( |
3173 | nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t flags, |
3174 | nsIAsyncVerifyRedirectCallback* callback) { |
3175 | LOG(("WebSocketChannel::AsyncOnChannelRedirect() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOnChannelRedirect() %p\n" , this); } } while (0); |
3176 | |
3177 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3177; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3178 | |
3179 | nsresult rv; |
3180 | |
3181 | nsCOMPtr<nsIURI> newuri; |
3182 | rv = newChannel->GetURI(getter_AddRefs(newuri)); |
3183 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3183); return rv; } } while (false); |
3184 | |
3185 | // newuri is expected to be http or https |
3186 | bool newuriIsHttps = newuri->SchemeIs("https"); |
3187 | |
3188 | // allow insecure->secure redirects for HTTP Strict Transport Security (from |
3189 | // ws://FOO to https://FOO (mapped to wss://FOO) |
3190 | if (!(flags & (nsIChannelEventSink::REDIRECT_INTERNAL | |
3191 | nsIChannelEventSink::REDIRECT_STS_UPGRADE))) { |
3192 | nsAutoCString newSpec; |
3193 | rv = newuri->GetSpec(newSpec); |
3194 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3194); return rv; } } while (false); |
3195 | |
3196 | LOG(("WebSocketChannel: Redirect to %s denied by configuration\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s denied by configuration\n" , newSpec.get()); } } while (0) |
3197 | newSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s denied by configuration\n" , newSpec.get()); } } while (0); |
3198 | return NS_ERROR_FAILURE; |
3199 | } |
3200 | |
3201 | if (mEncrypted && !newuriIsHttps) { |
3202 | nsAutoCString spec; |
3203 | if (NS_SUCCEEDED(newuri->GetSpec(spec))((bool)(__builtin_expect(!!(!NS_FAILED_impl(newuri->GetSpec (spec))), 1)))) { |
3204 | LOG(("WebSocketChannel: Redirect to %s violates encryption rule\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s violates encryption rule\n" , spec.get()); } } while (0) |
3205 | spec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect to %s violates encryption rule\n" , spec.get()); } } while (0); |
3206 | } |
3207 | return NS_ERROR_FAILURE; |
3208 | } |
3209 | |
3210 | nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(newChannel, &rv); |
3211 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3212 | LOG(("WebSocketChannel: Redirect could not QI to HTTP\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not QI to HTTP\n" ); } } while (0); |
3213 | return rv; |
3214 | } |
3215 | |
3216 | nsCOMPtr<nsIHttpChannelInternal> newUpgradeChannel = |
3217 | do_QueryInterface(newChannel, &rv); |
3218 | |
3219 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3220 | LOG(("WebSocketChannel: Redirect could not QI to HTTP Upgrade\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not QI to HTTP Upgrade\n" ); } } while (0); |
3221 | return rv; |
3222 | } |
3223 | |
3224 | // The redirect is likely OK |
3225 | |
3226 | newChannel->SetNotificationCallbacks(this); |
3227 | |
3228 | mEncrypted = newuriIsHttps; |
3229 | rv = NS_MutateURI(newuri) |
3230 | .SetScheme(mEncrypted ? "wss"_ns : "ws"_ns) |
3231 | .Finalize(mURI); |
3232 | |
3233 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3234 | LOG(("WebSocketChannel: Could not set the proper scheme\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Could not set the proper scheme\n" ); } } while (0); |
3235 | return rv; |
3236 | } |
3237 | |
3238 | mHttpChannel = newHttpChannel; |
3239 | mChannel = newUpgradeChannel; |
3240 | rv = SetupRequest(); |
3241 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3242 | LOG(("WebSocketChannel: Redirect could not SetupRequest()\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect could not SetupRequest()\n" ); } } while (0); |
3243 | return rv; |
3244 | } |
3245 | |
3246 | // Redirected-to URI may need to be delayed by 1-connecting-per-host and |
3247 | // delay-after-fail algorithms. So hold off calling OnRedirectVerifyCallback |
3248 | // until BeginOpen, when we know it's OK to proceed with new channel. |
3249 | mRedirectCallback = callback; |
3250 | |
3251 | // Mark old channel as successfully connected so we'll clear any FailDelay |
3252 | // associated with the old URI. Note: no need to also call OnStopSession: |
3253 | // it's a no-op for successful, already-connected channels. |
3254 | nsWSAdmissionManager::OnConnected(this); |
3255 | |
3256 | // ApplyForAdmission as if we were starting from fresh... |
3257 | mAddress.Truncate(); |
3258 | mOpenedHttpChannel = false; |
3259 | rv = ApplyForAdmission(); |
3260 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3261 | LOG(("WebSocketChannel: Redirect failed due to DNS failure\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: Redirect failed due to DNS failure\n" ); } } while (0); |
3262 | mRedirectCallback = nullptr; |
3263 | return rv; |
3264 | } |
3265 | |
3266 | return NS_OK; |
3267 | } |
3268 | |
3269 | // nsITimerCallback |
3270 | |
3271 | NS_IMETHODIMPnsresult |
3272 | WebSocketChannel::Notify(nsITimer* timer) { |
3273 | LOG(("WebSocketChannel::Notify() %p [%p]\n", this, timer))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Notify() %p [%p]\n" , this, timer); } } while (0); |
3274 | |
3275 | if (timer == mCloseTimer) { |
3276 | MOZ_ASSERT(mClientClosed, "Close Timeout without local close")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mClientClosed)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mClientClosed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mClientClosed" " (" "Close Timeout without local close" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientClosed" ") (" "Close Timeout without local close" ")"); do { *((volatile int*)__null) = 3276; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3277 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3277; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3278 | |
3279 | mCloseTimer = nullptr; |
3280 | if (mStopped || mServerClosed) { /* no longer relevant */ |
3281 | return NS_OK; |
3282 | } |
3283 | |
3284 | LOG(("WebSocketChannel:: Expecting Server Close - Timed Out\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Expecting Server Close - Timed Out\n" ); } } while (0); |
3285 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3286 | } else if (timer == mOpenTimer) { |
3287 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3287; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3288 | |
3289 | mOpenTimer = nullptr; |
3290 | LOG(("WebSocketChannel:: Connection Timed Out\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Connection Timed Out\n" ); } } while (0); |
3291 | if (mStopped || mServerClosed) { /* no longer relevant */ |
3292 | return NS_OK; |
3293 | } |
3294 | |
3295 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3296 | MOZ_PUSH_IGNORE_THREAD_SAFETYGCC diagnostic push
GCC diagnostic ignored "-Wthread-safety" |
3297 | // mReconnectDelayTimer is only modified on MainThread, we can read it |
3298 | // without a lock, but ONLY if we're on MainThread! And if we're not |
3299 | // on MainThread, it can't be mReconnectDelayTimer |
3300 | } else if (NS_IsMainThread() && timer == mReconnectDelayTimer) { |
3301 | MOZ_POP_THREAD_SAFETYGCC diagnostic pop |
3302 | MOZ_ASSERT(mConnecting == CONNECTING_DELAYED,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mConnecting == CONNECTING_DELAYED)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mConnecting == CONNECTING_DELAYED ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mConnecting == CONNECTING_DELAYED" " (" "woke up from delay w/o being delayed?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED" ") (" "woke up from delay w/o being delayed?" ")"); do { *(( volatile int*)__null) = 3303; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
3303 | "woke up from delay w/o being delayed?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mConnecting == CONNECTING_DELAYED)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mConnecting == CONNECTING_DELAYED ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mConnecting == CONNECTING_DELAYED" " (" "woke up from delay w/o being delayed?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED" ") (" "woke up from delay w/o being delayed?" ")"); do { *(( volatile int*)__null) = 3303; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
3304 | |
3305 | { |
3306 | MutexAutoLock lock(mMutex); |
3307 | mReconnectDelayTimer = nullptr; |
3308 | } |
3309 | LOG(("WebSocketChannel: connecting [this=%p] after reconnect delay", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: connecting [this=%p] after reconnect delay" , this); } } while (0); |
3310 | BeginOpen(false); |
3311 | } else if (timer == mPingTimer) { |
3312 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3312); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3312; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3313 | |
3314 | if (mClientClosed || mServerClosed || mRequestedClose) { |
3315 | // no point in worrying about ping now |
3316 | mPingTimer = nullptr; |
3317 | return NS_OK; |
3318 | } |
3319 | |
3320 | if (!mPingOutstanding) { |
3321 | // Ping interval must be non-null or PING was forced by OnNetworkChanged() |
3322 | MOZ_ASSERT(mPingInterval || mPingForced)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPingInterval || mPingForced)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mPingInterval || mPingForced ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mPingInterval || mPingForced", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval || mPingForced" ")"); do { *((volatile int*)__null) = 3322; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3323 | LOG(("nsWebSocketChannel:: Generating Ping\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Generating Ping\n" ); } } while (0); |
3324 | mPingOutstanding = 1; |
3325 | mPingForced = false; |
3326 | mPingTimer->InitWithCallback(this, mPingResponseTimeout, |
3327 | nsITimer::TYPE_ONE_SHOT); |
3328 | GeneratePing(); |
3329 | } else { |
3330 | LOG(("nsWebSocketChannel:: Timed out Ping\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsWebSocketChannel:: Timed out Ping\n" ); } } while (0); |
3331 | mPingTimer = nullptr; |
3332 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3333 | } |
3334 | } else if (timer == mLingeringCloseTimer) { |
3335 | LOG(("WebSocketChannel:: Lingering Close Timer"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Lingering Close Timer" ); } } while (0); |
3336 | CleanupConnection(); |
3337 | } else { |
3338 | MOZ_ASSERT(0, "Unknown Timer")do { static_assert( mozilla::detail::AssertionConditionType< decltype(0)>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("0" " (" "Unknown Timer" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ") (" "Unknown Timer" ")"); do { *((volatile int*)__null) = 3338; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3339 | } |
3340 | |
3341 | return NS_OK; |
3342 | } |
3343 | |
3344 | // nsINamed |
3345 | |
3346 | NS_IMETHODIMPnsresult |
3347 | WebSocketChannel::GetName(nsACString& aName) { |
3348 | aName.AssignLiteral("WebSocketChannel"); |
3349 | return NS_OK; |
3350 | } |
3351 | |
3352 | // nsIWebSocketChannel |
3353 | |
3354 | NS_IMETHODIMPnsresult |
3355 | WebSocketChannel::GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) { |
3356 | LOG(("WebSocketChannel::GetSecurityInfo() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::GetSecurityInfo() %p\n" , this); } } while (0); |
3357 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3357); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3357; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3358 | |
3359 | *aSecurityInfo = nullptr; |
3360 | |
3361 | if (mConnection) { |
3362 | nsresult rv = mConnection->GetSecurityInfo(aSecurityInfo); |
3363 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3364 | return rv; |
3365 | } |
3366 | return NS_OK; |
3367 | } |
3368 | |
3369 | if (mTransport) { |
3370 | nsCOMPtr<nsITLSSocketControl> tlsSocketControl; |
3371 | nsresult rv = |
3372 | mTransport->GetTlsSocketControl(getter_AddRefs(tlsSocketControl)); |
3373 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3374 | return rv; |
3375 | } |
3376 | nsCOMPtr<nsITransportSecurityInfo> securityInfo( |
3377 | do_QueryInterface(tlsSocketControl)); |
3378 | if (securityInfo) { |
3379 | securityInfo.forget(aSecurityInfo); |
3380 | } |
3381 | } |
3382 | return NS_OK; |
3383 | } |
3384 | |
3385 | NS_IMETHODIMPnsresult |
3386 | WebSocketChannel::AsyncOpen(nsIURI* aURI, const nsACString& aOrigin, |
3387 | JS::Handle<JS::Value> aOriginAttributes, |
3388 | uint64_t aInnerWindowID, |
3389 | nsIWebSocketListener* aListener, |
3390 | nsISupports* aContext, JSContext* aCx) { |
3391 | OriginAttributes attrs; |
3392 | if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { |
3393 | return NS_ERROR_INVALID_ARG; |
3394 | } |
3395 | return AsyncOpenNative(aURI, aOrigin, attrs, aInnerWindowID, aListener, |
3396 | aContext); |
3397 | } |
3398 | |
3399 | NS_IMETHODIMPnsresult |
3400 | WebSocketChannel::AsyncOpenNative(nsIURI* aURI, const nsACString& aOrigin, |
3401 | const OriginAttributes& aOriginAttributes, |
3402 | uint64_t aInnerWindowID, |
3403 | nsIWebSocketListener* aListener, |
3404 | nsISupports* aContext) { |
3405 | LOG(("WebSocketChannel::AsyncOpen() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() %p\n" , this); } } while (0); |
3406 | |
3407 | aOriginAttributes.CreateSuffix(mOriginSuffix); |
3408 | |
3409 | if (!NS_IsMainThread()) { |
3410 | MOZ_ASSERT(false, "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3410 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3411 | LOG(("WebSocketChannel::AsyncOpen() called off the main thread"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() called off the main thread" ); } } while (0); |
3412 | return NS_ERROR_UNEXPECTED; |
3413 | } |
3414 | |
3415 | if ((!aURI && !mIsServerSide) || !aListener) { |
3416 | LOG(("WebSocketChannel::AsyncOpen() Uri or Listener null"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen() Uri or Listener null" ); } } while (0); |
3417 | return NS_ERROR_UNEXPECTED; |
3418 | } |
3419 | |
3420 | if (mListenerMT || mWasOpened) return NS_ERROR_ALREADY_OPENED; |
3421 | |
3422 | nsresult rv; |
3423 | |
3424 | // Ensure target thread is set if RetargetDeliveryTo isn't called |
3425 | { |
3426 | auto lock = mTargetThread.Lock(); |
3427 | if (!lock.ref()) { |
3428 | lock.ref() = GetMainThreadSerialEventTarget(); |
3429 | } |
3430 | } |
3431 | |
3432 | mIOThread = mozilla::components::SocketTransport::Service(&rv); |
3433 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3434 | NS_WARNING("unable to continue without socket transport service")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without socket transport service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3434); |
3435 | return rv; |
3436 | } |
3437 | |
3438 | nsCOMPtr<nsIPrefBranch> prefService; |
3439 | prefService = mozilla::components::Preferences::Service(); |
3440 | |
3441 | if (prefService) { |
3442 | int32_t intpref; |
3443 | rv = |
3444 | prefService->GetIntPref("network.websocket.max-message-size", &intpref); |
3445 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3446 | mMaxMessageSize = clamped(intpref, 1024, INT32_MAX(2147483647)); |
3447 | } |
3448 | rv = prefService->GetIntPref("network.websocket.timeout.close", &intpref); |
3449 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3450 | mCloseTimeout = clamped(intpref, 1, 1800) * 1000; |
3451 | } |
3452 | rv = prefService->GetIntPref("network.websocket.timeout.open", &intpref); |
3453 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3454 | mOpenTimeout = clamped(intpref, 1, 1800) * 1000; |
3455 | } |
3456 | rv = prefService->GetIntPref("network.websocket.timeout.ping.request", |
3457 | &intpref); |
3458 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingInterval) { |
3459 | mPingInterval = clamped(intpref, 0, 86400) * 1000; |
3460 | } |
3461 | rv = prefService->GetIntPref("network.websocket.timeout.ping.response", |
3462 | &intpref); |
3463 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingTimeout) { |
3464 | mPingResponseTimeout = clamped(intpref, 1, 3600) * 1000; |
3465 | } |
3466 | rv = prefService->GetIntPref("network.websocket.max-connections", &intpref); |
3467 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3468 | mMaxConcurrentConnections = clamped(intpref, 1, 0xffff); |
3469 | } |
3470 | } |
3471 | |
3472 | int32_t sessionCount = -1; |
3473 | nsWSAdmissionManager::GetSessionCount(sessionCount); |
3474 | if (sessionCount >= 0) { |
3475 | LOG(("WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n" , this, sessionCount, mMaxConcurrentConnections); } } while ( 0) |
3476 | sessionCount, mMaxConcurrentConnections))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::AsyncOpen %p sessionCount=%d max=%d\n" , this, sessionCount, mMaxConcurrentConnections); } } while ( 0); |
3477 | } |
3478 | |
3479 | if (sessionCount >= mMaxConcurrentConnections) { |
3480 | LOG(("WebSocketChannel: max concurrency %d exceeded (%d)",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: max concurrency %d exceeded (%d)" , mMaxConcurrentConnections, sessionCount); } } while (0) |
3481 | mMaxConcurrentConnections, sessionCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel: max concurrency %d exceeded (%d)" , mMaxConcurrentConnections, sessionCount); } } while (0); |
3482 | |
3483 | // WebSocket connections are expected to be long lived, so return |
3484 | // an error here instead of queueing |
3485 | return NS_ERROR_SOCKET_CREATE_FAILED; |
3486 | } |
3487 | |
3488 | mInnerWindowID = aInnerWindowID; |
3489 | mOriginalURI = aURI; |
3490 | mURI = mOriginalURI; |
3491 | mOrigin = aOrigin; |
3492 | |
3493 | if (mIsServerSide) { |
3494 | // IncrementSessionCount(); |
3495 | mWasOpened = 1; |
3496 | mListenerMT = new ListenerAndContextContainer(aListener, aContext); |
3497 | rv = mServerTransportProvider->SetListener(this); |
3498 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3498; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3499 | mServerTransportProvider = nullptr; |
3500 | |
3501 | return NS_OK; |
3502 | } |
3503 | |
3504 | mURI->GetHostPort(mHost); |
3505 | |
3506 | mRandomGenerator = mozilla::components::RandomGenerator::Service(&rv); |
3507 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3508 | NS_WARNING("unable to continue without random number generator")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without random number generator" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3508); |
3509 | return rv; |
3510 | } |
3511 | |
3512 | nsCOMPtr<nsIURI> localURI; |
3513 | nsCOMPtr<nsIChannel> localChannel; |
3514 | |
3515 | rv = NS_MutateURI(mURI) |
3516 | .SetScheme(mEncrypted ? "https"_ns : "http"_ns) |
3517 | .Finalize(localURI); |
3518 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3518); return rv; } } while (false); |
3519 | |
3520 | nsCOMPtr<nsIIOService> ioService; |
3521 | ioService = mozilla::components::IO::Service(&rv); |
3522 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3523 | NS_WARNING("unable to continue without io service")NS_DebugBreak(NS_DEBUG_WARNING, "unable to continue without io service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3523); |
3524 | return rv; |
3525 | } |
3526 | |
3527 | // Ideally we'd call newChannelFromURIWithLoadInfo here, but that doesn't |
3528 | // allow setting proxy uri/flags |
3529 | rv = ioService->NewChannelFromURIWithProxyFlags( |
3530 | localURI, mURI, |
3531 | nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY | |
3532 | nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY | |
3533 | nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL, |
3534 | mLoadInfo->LoadingNode(), mLoadInfo->GetLoadingPrincipal(), |
3535 | mLoadInfo->TriggeringPrincipal(), mLoadInfo->GetSecurityFlags(), |
3536 | mLoadInfo->InternalContentPolicyType(), getter_AddRefs(localChannel)); |
3537 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3537); return rv; } } while (false); |
3538 | |
3539 | // Please note that we still call SetLoadInfo on the channel because |
3540 | // we want the same instance of the loadInfo to be set on the channel. |
3541 | rv = localChannel->SetLoadInfo(mLoadInfo); |
3542 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3542); return rv; } } while (false); |
3543 | |
3544 | // Pass most GetInterface() requests through to our instantiator, but handle |
3545 | // nsIChannelEventSink in this object in order to deal with redirects |
3546 | localChannel->SetNotificationCallbacks(this); |
3547 | |
3548 | class MOZ_STACK_CLASS CleanUpOnFailure { |
3549 | public: |
3550 | explicit CleanUpOnFailure(WebSocketChannel* aWebSocketChannel) |
3551 | : mWebSocketChannel(aWebSocketChannel) {} |
3552 | |
3553 | ~CleanUpOnFailure() { |
3554 | if (!mWebSocketChannel->mWasOpened) { |
3555 | mWebSocketChannel->mChannel = nullptr; |
3556 | mWebSocketChannel->mHttpChannel = nullptr; |
3557 | } |
3558 | } |
3559 | |
3560 | WebSocketChannel* mWebSocketChannel; |
3561 | }; |
3562 | |
3563 | CleanUpOnFailure cuof(this); |
3564 | |
3565 | mChannel = do_QueryInterface(localChannel, &rv); |
3566 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3566); return rv; } } while (false); |
3567 | |
3568 | mHttpChannel = do_QueryInterface(localChannel, &rv); |
3569 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3569); return rv; } } while (false); |
3570 | |
3571 | rv = SetupRequest(); |
3572 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3573 | |
3574 | mPrivateBrowsing = NS_UsePrivateBrowsing(localChannel); |
3575 | |
3576 | if (mConnectionLogService && !mPrivateBrowsing) { |
3577 | mConnectionLogService->AddHost(mHost, mSerial, |
3578 | BaseWebSocketChannel::mEncrypted); |
3579 | } |
3580 | |
3581 | rv = ApplyForAdmission(); |
3582 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3583 | |
3584 | // Register for prefs change notifications |
3585 | nsCOMPtr<nsIObserverService> observerService = |
3586 | mozilla::services::GetObserverService(); |
3587 | if (!observerService) { |
3588 | NS_WARNING("failed to get observer service")NS_DebugBreak(NS_DEBUG_WARNING, "failed to get observer service" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3588); |
3589 | return NS_ERROR_FAILURE; |
3590 | } |
3591 | |
3592 | rv = observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC"network:link-status-changed", false); |
3593 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3593)) { |
3594 | return rv; |
3595 | } |
3596 | |
3597 | // Only set these if the open was successful: |
3598 | // |
3599 | mWasOpened = 1; |
3600 | mListenerMT = new ListenerAndContextContainer(aListener, aContext); |
3601 | IncrementSessionCount(); |
3602 | |
3603 | return rv; |
3604 | } |
3605 | |
3606 | NS_IMETHODIMPnsresult |
3607 | WebSocketChannel::Close(uint16_t code, const nsACString& reason) { |
3608 | LOG(("WebSocketChannel::Close() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() %p\n" , this); } } while (0); |
3609 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3609; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3610 | |
3611 | { |
3612 | MutexAutoLock lock(mMutex); |
3613 | |
3614 | if (mRequestedClose) { |
3615 | return NS_OK; |
3616 | } |
3617 | |
3618 | if (mStopped) { |
3619 | return NS_ERROR_NOT_AVAILABLE; |
3620 | } |
3621 | |
3622 | // The API requires the UTF-8 string to be 123 or less bytes |
3623 | if (reason.Length() > 123) return NS_ERROR_ILLEGAL_VALUE; |
3624 | |
3625 | mRequestedClose = true; |
3626 | mScriptCloseReason = reason; |
3627 | mScriptCloseCode = code; |
3628 | |
3629 | if (mDataStarted) { |
3630 | return mIOThread->Dispatch( |
3631 | new OutboundEnqueuer(this, |
3632 | new OutboundMessage(kMsgTypeFin, VoidCString())), |
3633 | nsIEventTarget::DISPATCH_NORMAL); |
3634 | } |
3635 | |
3636 | mStopped = true; |
3637 | } |
3638 | |
3639 | nsresult rv; |
3640 | if (code == CLOSE_GOING_AWAY) { |
3641 | // Not an error: for example, tab has closed or navigated away |
3642 | LOG(("WebSocketChannel::Close() GOING_AWAY without transport."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() GOING_AWAY without transport." ); } } while (0); |
3643 | rv = NS_OK; |
3644 | } else { |
3645 | LOG(("WebSocketChannel::Close() without transport - error."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::Close() without transport - error." ); } } while (0); |
3646 | rv = NS_ERROR_NOT_CONNECTED; |
3647 | } |
3648 | |
3649 | DoStopSession(rv); |
3650 | return rv; |
3651 | } |
3652 | |
3653 | NS_IMETHODIMPnsresult |
3654 | WebSocketChannel::SendMsg(const nsACString& aMsg) { |
3655 | LOG(("WebSocketChannel::SendMsg() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendMsg() %p\n" , this); } } while (0); |
3656 | |
3657 | return SendMsgCommon(aMsg, false, aMsg.Length()); |
3658 | } |
3659 | |
3660 | NS_IMETHODIMPnsresult |
3661 | WebSocketChannel::SendBinaryMsg(const nsACString& aMsg) { |
3662 | LOG(("WebSocketChannel::SendBinaryMsg() %p len=%zu\n", this, aMsg.Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendBinaryMsg() %p len=%zu\n" , this, aMsg.Length()); } } while (0); |
3663 | return SendMsgCommon(aMsg, true, aMsg.Length()); |
3664 | } |
3665 | |
3666 | NS_IMETHODIMPnsresult |
3667 | WebSocketChannel::SendBinaryStream(nsIInputStream* aStream, uint32_t aLength) { |
3668 | LOG(("WebSocketChannel::SendBinaryStream() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::SendBinaryStream() %p\n" , this); } } while (0); |
3669 | |
3670 | return SendMsgCommon(VoidCString(), true, aLength, aStream); |
3671 | } |
3672 | |
3673 | nsresult WebSocketChannel::SendMsgCommon(const nsACString& aMsg, bool aIsBinary, |
3674 | uint32_t aLength, |
3675 | nsIInputStream* aStream) { |
3676 | MOZ_ASSERT(IsOnTargetThread(), "not target thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsOnTargetThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsOnTargetThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnTargetThread()" " (" "not target thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnTargetThread()" ") (" "not target thread" ")"); do { *((volatile int*)__null ) = 3676; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3677 | |
3678 | if (!mDataStarted) { |
3679 | LOG(("WebSocketChannel:: Error: data not started yet\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: data not started yet\n" ); } } while (0); |
3680 | return NS_ERROR_UNEXPECTED; |
3681 | } |
3682 | |
3683 | if (mRequestedClose) { |
3684 | LOG(("WebSocketChannel:: Error: send when closed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: send when closed\n" ); } } while (0); |
3685 | return NS_ERROR_UNEXPECTED; |
3686 | } |
3687 | |
3688 | if (mStopped) { |
3689 | LOG(("WebSocketChannel:: Error: send when stopped\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: send when stopped\n" ); } } while (0); |
3690 | return NS_ERROR_NOT_CONNECTED; |
3691 | } |
3692 | |
3693 | MOZ_ASSERT(mMaxMessageSize >= 0, "max message size negative")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mMaxMessageSize >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mMaxMessageSize >= 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("mMaxMessageSize >= 0" " (" "max message size negative" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMaxMessageSize >= 0" ") (" "max message size negative" ")"); do { *((volatile int *)__null) = 3693; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3694 | if (aLength > static_cast<uint32_t>(mMaxMessageSize)) { |
3695 | LOG(("WebSocketChannel:: Error: message too big\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel:: Error: message too big\n" ); } } while (0); |
3696 | return NS_ERROR_FILE_TOO_BIG; |
3697 | } |
3698 | |
3699 | if (mConnectionLogService && !mPrivateBrowsing) { |
3700 | mConnectionLogService->NewMsgSent(mHost, mSerial, aLength); |
3701 | LOG(("Added new msg sent for %s", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added new msg sent for %s" , mHost.get()); } } while (0); |
3702 | } |
3703 | |
3704 | return mIOThread->Dispatch( |
3705 | aStream |
3706 | ? new OutboundEnqueuer(this, new OutboundMessage(aStream, aLength)) |
3707 | : new OutboundEnqueuer( |
3708 | this, |
3709 | new OutboundMessage( |
3710 | aIsBinary ? kMsgTypeBinaryString : kMsgTypeString, aMsg)), |
3711 | nsIEventTarget::DISPATCH_NORMAL); |
3712 | } |
3713 | |
3714 | // nsIHttpUpgradeListener |
3715 | |
3716 | NS_IMETHODIMPnsresult |
3717 | WebSocketChannel::OnTransportAvailable(nsISocketTransport* aTransport, |
3718 | nsIAsyncInputStream* aSocketIn, |
3719 | nsIAsyncOutputStream* aSocketOut) { |
3720 | if (!NS_IsMainThread()) { |
3721 | return NS_DispatchToMainThread( |
3722 | new CallOnTransportAvailable(this, aTransport, aSocketIn, aSocketOut)); |
3723 | } |
3724 | |
3725 | LOG(("WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n" , this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK); } } while (0) |
3726 | this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable %p [%p %p %p] rcvdonstart=%d\n" , this, aTransport, aSocketIn, aSocketOut, mGotUpgradeOK); } } while (0); |
3727 | |
3728 | if (mStopped) { |
3729 | LOG(("WebSocketChannel::OnTransportAvailable: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Already stopped" ); } } while (0); |
3730 | return NS_OK; |
3731 | } |
3732 | |
3733 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3733; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3734 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport, "OTA duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OTA duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OTA duplicated" ")"); do { *((volatile int*)__null) = 3734; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3735 | MOZ_ASSERT(aSocketIn, "OTA with invalid socketIn")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSocketIn)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSocketIn))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSocketIn" " (" "OTA with invalid socketIn" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3735); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSocketIn" ") (" "OTA with invalid socketIn" ")"); do { *((volatile int*)__null ) = 3735; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3736 | |
3737 | mTransport = aTransport; |
3738 | mSocketIn = aSocketIn; |
3739 | mSocketOut = aSocketOut; |
3740 | |
3741 | nsresult rv; |
3742 | rv = mTransport->SetEventSink(nullptr, nullptr); |
3743 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3744 | rv = mTransport->SetSecurityCallbacks(this); |
3745 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3746 | |
3747 | return OnTransportAvailableInternal(); |
3748 | } |
3749 | |
3750 | NS_IMETHODIMPnsresult |
3751 | WebSocketChannel::OnWebSocketConnectionAvailable( |
3752 | WebSocketConnectionBase* aConnection) { |
3753 | if (!NS_IsMainThread()) { |
3754 | RefPtr<WebSocketChannel> self = this; |
3755 | RefPtr<WebSocketConnectionBase> connection = aConnection; |
3756 | return NS_DispatchToMainThread(NS_NewRunnableFunction( |
3757 | "WebSocketChannel::OnWebSocketConnectionAvailable", |
3758 | [self, connection]() { |
3759 | self->OnWebSocketConnectionAvailable(connection); |
3760 | })); |
3761 | } |
3762 | |
3763 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0) |
3764 | ("WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0) |
3765 | "rcvdonstart=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0) |
3766 | this, aConnection, mGotUpgradeOK))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] " "rcvdonstart=%d\n", this, aConnection, mGotUpgradeOK); } } while (0); |
3767 | |
3768 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3768; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3769 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3770; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
3770 | "OnWebSocketConnectionAvailable duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3770; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
3771 | MOZ_ASSERT(aConnection)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aConnection)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aConnection))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aConnection", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aConnection" ")"); do { *((volatile int*)__null) = 3771; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3772 | |
3773 | if (mStopped) { |
3774 | LOG(("WebSocketChannel::OnWebSocketConnectionAvailable: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnWebSocketConnectionAvailable: Already stopped" ); } } while (0); |
3775 | aConnection->Close(); |
3776 | return NS_OK; |
3777 | } |
3778 | |
3779 | nsresult rv = aConnection->Init(this); |
3780 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3781 | return rv; |
3782 | } |
3783 | |
3784 | mConnection = aConnection; |
3785 | // Note: mIOThread will be IPDL background thread. |
3786 | mConnection->GetIoTarget(getter_AddRefs(mIOThread)); |
3787 | return OnTransportAvailableInternal(); |
3788 | } |
3789 | |
3790 | nsresult WebSocketChannel::OnTransportAvailableInternal() { |
3791 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3791; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3792 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3793; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
3793 | "OnWebSocketConnectionAvailable duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OnWebSocketConnectionAvailable duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3793; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
3794 | MOZ_ASSERT(mSocketIn || mConnection)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSocketIn || mConnection)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSocketIn || mConnection))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSocketIn || mConnection" , "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSocketIn || mConnection" ")"); do { *((volatile int*)__null) = 3794; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3795 | |
3796 | mRecvdHttpUpgradeTransport = 1; |
3797 | if (mGotUpgradeOK) { |
3798 | // We're now done CONNECTING, which means we can now open another, |
3799 | // perhaps parallel, connection to the same host if one |
3800 | // is pending |
3801 | nsWSAdmissionManager::OnConnected(this); |
3802 | |
3803 | return CallStartWebsocketData(); |
3804 | } |
3805 | |
3806 | if (mIsServerSide) { |
3807 | if (!mNegotiatedExtensions.IsEmpty()) { |
3808 | bool clientNoContextTakeover; |
3809 | bool serverNoContextTakeover; |
3810 | int32_t clientMaxWindowBits; |
3811 | int32_t serverMaxWindowBits; |
3812 | |
3813 | nsresult rv = ParseWebSocketExtension( |
3814 | mNegotiatedExtensions, eParseServerSide, clientNoContextTakeover, |
3815 | serverNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits); |
3816 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), "illegal value provided by server")do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " (" "illegal value provided by server" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3816); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "illegal value provided by server" ")"); do { *((volatile int*)__null) = 3816; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3817 | |
3818 | if (clientMaxWindowBits == -1) { |
3819 | clientMaxWindowBits = 15; |
3820 | } |
3821 | if (serverMaxWindowBits == -1) { |
3822 | serverMaxWindowBits = 15; |
3823 | } |
3824 | |
3825 | MutexAutoLock lock(mCompressorMutex); |
3826 | mPMCECompressor = MakeUnique<PMCECompression>( |
3827 | serverNoContextTakeover, serverMaxWindowBits, clientMaxWindowBits); |
3828 | if (mPMCECompressor->Active()) { |
3829 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3830 | ("WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3831 | "context takeover, serverMaxWindowBits=%d, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3832 | "clientMaxWindowBits=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3833 | serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0) |
3834 | clientMaxWindowBits))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: PMCE negotiated, %susing " "context takeover, serverMaxWindowBits=%d, " "clientMaxWindowBits=%d\n" , serverNoContextTakeover ? "NOT " : "", serverMaxWindowBits, clientMaxWindowBits); } } while (0); |
3835 | |
3836 | mNegotiatedExtensions = "permessage-deflate"; |
3837 | } else { |
3838 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE " "compression object\n"); } } while (0) |
3839 | ("WebSocketChannel::OnTransportAvailable: Cannot init PMCE "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE " "compression object\n"); } } while (0) |
3840 | "compression object\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnTransportAvailable: Cannot init PMCE " "compression object\n"); } } while (0); |
3841 | mPMCECompressor = nullptr; |
3842 | AbortSession(NS_ERROR_UNEXPECTED); |
3843 | return NS_ERROR_UNEXPECTED; |
3844 | } |
3845 | } |
3846 | |
3847 | return CallStartWebsocketData(); |
3848 | } |
3849 | |
3850 | return NS_OK; |
3851 | } |
3852 | |
3853 | NS_IMETHODIMPnsresult |
3854 | WebSocketChannel::OnUpgradeFailed(nsresult aErrorCode) { |
3855 | // When socket process is enabled, this could be called on background thread. |
3856 | |
3857 | LOG(("WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %" PRIx32 "]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %" "x" "]", this, static_cast<uint32_t>(aErrorCode)); } } while (0) |
3858 | static_cast<uint32_t>(aErrorCode)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed() %p [aErrorCode %" "x" "]", this, static_cast<uint32_t>(aErrorCode)); } } while (0); |
3859 | |
3860 | if (mStopped) { |
3861 | LOG(("WebSocketChannel::OnUpgradeFailed: Already stopped"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnUpgradeFailed: Already stopped" ); } } while (0); |
3862 | return NS_OK; |
3863 | } |
3864 | |
3865 | MOZ_ASSERT(!mRecvdHttpUpgradeTransport, "OTA already called")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mRecvdHttpUpgradeTransport)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mRecvdHttpUpgradeTransport) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mRecvdHttpUpgradeTransport" " (" "OTA already called" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OTA already called" ")"); do { *((volatile int*)__null ) = 3865; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3866 | |
3867 | AbortSession(aErrorCode); |
3868 | return NS_OK; |
3869 | } |
3870 | |
3871 | // nsIRequestObserver (from nsIStreamListener) |
3872 | |
3873 | NS_IMETHODIMPnsresult |
3874 | WebSocketChannel::OnStartRequest(nsIRequest* aRequest) { |
3875 | LOG(("WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n" , this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport ); } } while (0) |
3876 | this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest(): %p [%p %p] recvdhttpupgrade=%d\n" , this, aRequest, mHttpChannel.get(), mRecvdHttpUpgradeTransport ); } } while (0); |
3877 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3877; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3878 | MOZ_ASSERT(!mGotUpgradeOK, "OTA duplicated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mGotUpgradeOK)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mGotUpgradeOK))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mGotUpgradeOK" " (" "OTA duplicated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3878); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mGotUpgradeOK" ") (" "OTA duplicated" ")"); do { *((volatile int*)__null) = 3878; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3879 | |
3880 | if (mStopped) { |
3881 | LOG(("WebSocketChannel::OnStartRequest: Channel Already Done\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Channel Already Done\n" ); } } while (0); |
3882 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
3883 | return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3884 | } |
3885 | |
3886 | nsresult rv; |
3887 | uint32_t status; |
3888 | char *val, *token; |
3889 | |
3890 | rv = mHttpChannel->GetResponseStatus(&status); |
3891 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3892 | nsresult httpStatus; |
3893 | rv = NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3894 | |
3895 | // If we failed to connect due to unsuccessful TLS handshake, we must |
3896 | // propagate a specific error to mozilla::dom::WebSocketImpl so it can set |
3897 | // status code to 1015. Otherwise return |
3898 | // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED. |
3899 | if (NS_SUCCEEDED(mHttpChannel->GetStatus(&httpStatus))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mHttpChannel-> GetStatus(&httpStatus))), 1)))) { |
3900 | uint32_t errorClass; |
3901 | nsCOMPtr<nsINSSErrorsService> errSvc; |
3902 | errSvc = mozilla::components::NSSErrors::Service(); |
3903 | // If GetErrorClass succeeds httpStatus is TLS related failure. |
3904 | if (errSvc && |
3905 | NS_SUCCEEDED(errSvc->GetErrorClass(httpStatus, &errorClass))((bool)(__builtin_expect(!!(!NS_FAILED_impl(errSvc->GetErrorClass (httpStatus, &errorClass))), 1)))) { |
3906 | rv = NS_ERROR_NET_INADEQUATE_SECURITY; |
3907 | } |
3908 | } |
3909 | |
3910 | LOG(("WebSocketChannel::OnStartRequest: No HTTP Response\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: No HTTP Response\n" ); } } while (0); |
3911 | AbortSession(rv); |
3912 | return rv; |
3913 | } |
3914 | |
3915 | LOG(("WebSocketChannel::OnStartRequest: HTTP status %d\n", status))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: HTTP status %d\n" , status); } } while (0); |
3916 | nsCOMPtr<nsIHttpChannelInternal> internalChannel = |
3917 | do_QueryInterface(mHttpChannel); |
3918 | uint32_t versionMajor, versionMinor; |
3919 | rv = internalChannel->GetResponseVersion(&versionMajor, &versionMinor); |
3920 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || |
3921 | !((versionMajor == 1 && versionMinor != 0) || versionMajor == 2) || |
3922 | (versionMajor == 1 && status != 101) || |
3923 | (versionMajor == 2 && status != 200)) { |
3924 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
3925 | return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3926 | } |
3927 | |
3928 | if (versionMajor == 1) { |
3929 | // These are only present on http/1.x websocket upgrades |
3930 | nsAutoCString respUpgrade; |
3931 | rv = mHttpChannel->GetResponseHeader("Upgrade"_ns, respUpgrade); |
3932 | |
3933 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3934 | rv = NS_ERROR_ILLEGAL_VALUE; |
3935 | if (!respUpgrade.IsEmpty()) { |
3936 | val = respUpgrade.BeginWriting(); |
3937 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
3938 | if (nsCRT::strcasecmp(token, "Websocket") == 0) { |
3939 | rv = NS_OK; |
3940 | break; |
3941 | } |
3942 | } |
3943 | } |
3944 | } |
3945 | |
3946 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3947 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Upgrade: websocket not found\n"); } } while (0) |
3948 | ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Upgrade: websocket not found\n"); } } while (0) |
3949 | "HTTP response header Upgrade: websocket not found\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Upgrade: websocket not found\n"); } } while (0); |
3950 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
3951 | return rv; |
3952 | } |
3953 | |
3954 | nsAutoCString respConnection; |
3955 | rv = mHttpChannel->GetResponseHeader("Connection"_ns, respConnection); |
3956 | |
3957 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3958 | rv = NS_ERROR_ILLEGAL_VALUE; |
3959 | if (!respConnection.IsEmpty()) { |
3960 | val = respConnection.BeginWriting(); |
3961 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
3962 | if (nsCRT::strcasecmp(token, "Upgrade") == 0) { |
3963 | rv = NS_OK; |
3964 | break; |
3965 | } |
3966 | } |
3967 | } |
3968 | } |
3969 | |
3970 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3971 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header 'Connection: Upgrade' not found\n"); } } while (0) |
3972 | ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header 'Connection: Upgrade' not found\n"); } } while (0) |
3973 | "HTTP response header 'Connection: Upgrade' not found\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header 'Connection: Upgrade' not found\n"); } } while (0); |
3974 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
3975 | return rv; |
3976 | } |
3977 | |
3978 | nsAutoCString respAccept; |
3979 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Accept"_ns, respAccept); |
3980 | |
3981 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty() || |
3982 | !respAccept.Equals(mHashedSecret)) { |
3983 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Sec-WebSocket-Accept check failed\n"); } } while (0) |
3984 | ("WebSocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Sec-WebSocket-Accept check failed\n"); } } while (0) |
3985 | "HTTP response header Sec-WebSocket-Accept check failed\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: " "HTTP response header Sec-WebSocket-Accept check failed\n"); } } while (0); |
3986 | LOG(("WebSocketChannel::OnStartRequest: Expected %s received %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Expected %s received %s\n" , mHashedSecret.get(), respAccept.get()); } } while (0) |
3987 | mHashedSecret.get(), respAccept.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStartRequest: Expected %s received %s\n" , mHashedSecret.get(), respAccept.get()); } } while (0); |
3988 | #ifdef FUZZING |
3989 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty()) { |
3990 | #endif |
3991 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
3992 | return NS_ERROR_ILLEGAL_VALUE; |
3993 | #ifdef FUZZING |
3994 | } |
3995 | #endif |
3996 | } |
3997 | } |
3998 | |
3999 | // If we sent a sub protocol header, verify the response matches. |
4000 | // If response contains protocol that was not in request, fail. |
4001 | // If response contained no protocol header, set to "" so the protocol |
4002 | // attribute of the WebSocket JS object reflects that |
4003 | if (!mProtocol.IsEmpty()) { |
4004 | nsAutoCString respProtocol; |
4005 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Protocol"_ns, |
4006 | respProtocol); |
4007 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
4008 | rv = NS_ERROR_ILLEGAL_VALUE; |
4009 | val = mProtocol.BeginWriting(); |
4010 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
4011 | if (strcmp(token, respProtocol.get()) == 0) { |
4012 | rv = NS_OK; |
4013 | break; |
4014 | } |
4015 | } |
4016 | |
4017 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
4018 | LOG(("WebsocketChannel::OnStartRequest: subprotocol %s confirmed",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: subprotocol %s confirmed" , respProtocol.get()); } } while (0) |
4019 | respProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: subprotocol %s confirmed" , respProtocol.get()); } } while (0); |
4020 | mProtocol = respProtocol; |
4021 | } else { |
4022 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0) |
4023 | ("WebsocketChannel::OnStartRequest: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0) |
4024 | "Server replied with non-matching subprotocol [%s]: aborting",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0) |
4025 | respProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest: " "Server replied with non-matching subprotocol [%s]: aborting" , respProtocol.get()); } } while (0); |
4026 | mProtocol.Truncate(); |
4027 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
4028 | return NS_ERROR_ILLEGAL_VALUE; |
4029 | } |
4030 | } else { |
4031 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0) |
4032 | ("WebsocketChannel::OnStartRequest "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0) |
4033 | "subprotocol [%s] not found - none returned",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0) |
4034 | mProtocol.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebsocketChannel::OnStartRequest " "subprotocol [%s] not found - none returned", mProtocol.get( )); } } while (0); |
4035 | mProtocol.Truncate(); |
4036 | } |
4037 | } |
4038 | |
4039 | rv = HandleExtensions(); |
4040 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
4041 | |
4042 | // Update mEffectiveURL for off main thread URI access. |
4043 | nsCOMPtr<nsIURI> uri = mURI ? mURI : mOriginalURI; |
4044 | nsAutoCString spec; |
4045 | rv = uri->GetSpec(spec); |
4046 | MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 4046; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4047 | CopyUTF8toUTF16(spec, mEffectiveURL); |
4048 | |
4049 | mGotUpgradeOK = 1; |
4050 | if (mRecvdHttpUpgradeTransport) { |
4051 | // We're now done CONNECTING, which means we can now open another, |
4052 | // perhaps parallel, connection to the same host if one |
4053 | // is pending |
4054 | nsWSAdmissionManager::OnConnected(this); |
4055 | |
4056 | return CallStartWebsocketData(); |
4057 | } |
4058 | |
4059 | return NS_OK; |
4060 | } |
4061 | |
4062 | NS_IMETHODIMPnsresult |
4063 | WebSocketChannel::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { |
4064 | LOG(("WebSocketChannel::OnStopRequest() %p [%p %p %" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStopRequest() %p [%p %p %" "x" "]\n", this, aRequest, mHttpChannel.get(), static_cast< uint32_t>(aStatusCode)); } } while (0) |
4065 | aRequest, mHttpChannel.get(), static_cast<uint32_t>(aStatusCode)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnStopRequest() %p [%p %p %" "x" "]\n", this, aRequest, mHttpChannel.get(), static_cast< uint32_t>(aStatusCode)); } } while (0); |
4066 | MOZ_ASSERT(NS_IsMainThread(), "not main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "not main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 4066; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4067 | |
4068 | // OnTransportAvailable won't be called if the request is stopped with |
4069 | // an error. Abort the session now instead of waiting for timeout. |
4070 | if (NS_FAILED(aStatusCode)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatusCode)), 0)) ) && !mRecvdHttpUpgradeTransport) { |
4071 | AbortSession(aStatusCode); |
4072 | } |
4073 | |
4074 | ReportConnectionTelemetry(aStatusCode); |
4075 | |
4076 | // This is the end of the HTTP upgrade transaction, the |
4077 | // upgraded streams live on |
4078 | |
4079 | mChannel = nullptr; |
4080 | mHttpChannel = nullptr; |
4081 | mLoadGroup = nullptr; |
4082 | mCallbacks = nullptr; |
4083 | |
4084 | return NS_OK; |
4085 | } |
4086 | |
4087 | // nsIInputStreamCallback |
4088 | |
4089 | NS_IMETHODIMPnsresult |
4090 | WebSocketChannel::OnInputStreamReady(nsIAsyncInputStream* aStream) { |
4091 | LOG(("WebSocketChannel::OnInputStreamReady() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady() %p\n" , this); } } while (0); |
4092 | MOZ_DIAGNOSTIC_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4092); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4092; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4093 | |
4094 | if (!mSocketIn) { // did we we clean up the socket after scheduling |
4095 | // InputReady? |
4096 | return NS_OK; |
4097 | } |
4098 | |
4099 | // this is after the http upgrade - so we are speaking websockets |
4100 | char buffer[2048]; |
4101 | uint32_t count; |
4102 | nsresult rv; |
4103 | |
4104 | do { |
4105 | rv = mSocketIn->Read((char*)buffer, sizeof(buffer), &count); |
4106 | LOG(("WebSocketChannel::OnInputStreamReady: read %u rv %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady: read %u rv %" "x" "\n", count, static_cast<uint32_t>(rv)); } } while (0) |
4107 | count, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnInputStreamReady: read %u rv %" "x" "\n", count, static_cast<uint32_t>(rv)); } } while (0); |
4108 | |
4109 | if (rv == NS_BASE_STREAM_WOULD_BLOCK) { |
4110 | mSocketIn->AsyncWait(this, 0, 0, mIOThread); |
4111 | return NS_OK; |
4112 | } |
4113 | |
4114 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4115 | AbortSession(rv); |
4116 | return rv; |
4117 | } |
4118 | |
4119 | if (count == 0) { |
4120 | AbortSession(NS_BASE_STREAM_CLOSED); |
4121 | return NS_OK; |
4122 | } |
4123 | |
4124 | if (mStopped) { |
4125 | continue; |
4126 | } |
4127 | |
4128 | rv = ProcessInput((uint8_t*)buffer, count); |
4129 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4130 | AbortSession(rv); |
4131 | return rv; |
4132 | } |
4133 | } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mSocketIn); |
4134 | |
4135 | return NS_OK; |
4136 | } |
4137 | |
4138 | // nsIOutputStreamCallback |
4139 | |
4140 | NS_IMETHODIMPnsresult |
4141 | WebSocketChannel::OnOutputStreamReady(nsIAsyncOutputStream* aStream) { |
4142 | LOG(("WebSocketChannel::OnOutputStreamReady() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady() %p\n" , this); } } while (0); |
4143 | MOZ_DIAGNOSTIC_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4143); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4143; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4144 | nsresult rv; |
4145 | |
4146 | if (!mCurrentOut) PrimeNewOutgoingMessage(); |
4147 | |
4148 | while (mCurrentOut && mSocketOut) { |
4149 | const char* sndBuf; |
4150 | uint32_t toSend; |
4151 | uint32_t amtSent; |
4152 | |
4153 | if (mHdrOut) { |
4154 | sndBuf = (const char*)mHdrOut; |
4155 | toSend = mHdrOutToSend; |
4156 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0) |
4157 | ("WebSocketChannel::OnOutputStreamReady: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0) |
4158 | "Try to send %u of hdr/copybreak\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0) |
4159 | toSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady: " "Try to send %u of hdr/copybreak\n", toSend); } } while (0); |
4160 | } else { |
4161 | sndBuf = (char*)mCurrentOut->BeginReading() + mCurrentOutSent; |
4162 | toSend = mCurrentOut->Length() - mCurrentOutSent; |
4163 | if (toSend > 0) { |
4164 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0) |
4165 | ("WebSocketChannel::OnOutputStreamReady [%p]: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0) |
4166 | "Try to send %u of data\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0) |
4167 | this, toSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: " "Try to send %u of data\n", this, toSend); } } while (0); |
4168 | } |
4169 | } |
4170 | |
4171 | if (toSend == 0) { |
4172 | amtSent = 0; |
4173 | } else { |
4174 | rv = mSocketOut->Write(sndBuf, toSend, &amtSent); |
4175 | LOG(("WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" "x" "\n", this, amtSent, static_cast<uint32_t>(rv)); } } while (0) |
4176 | "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" "x" "\n", this, amtSent, static_cast<uint32_t>(rv)); } } while (0) |
4177 | this, amtSent, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" "x" "\n", this, amtSent, static_cast<uint32_t>(rv)); } } while (0); |
4178 | |
4179 | if (rv == NS_BASE_STREAM_WOULD_BLOCK) { |
4180 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4181 | return NS_OK; |
4182 | } |
4183 | |
4184 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4185 | AbortSession(rv); |
4186 | return NS_OK; |
4187 | } |
4188 | } |
4189 | |
4190 | if (mHdrOut) { |
4191 | if (amtSent == toSend) { |
4192 | mHdrOut = nullptr; |
4193 | mHdrOutToSend = 0; |
4194 | } else { |
4195 | mHdrOut += amtSent; |
4196 | mHdrOutToSend -= amtSent; |
4197 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4198 | } |
4199 | } else { |
4200 | if (amtSent == toSend) { |
4201 | if (!mStopped) { |
4202 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
4203 | target->Dispatch( |
4204 | new CallAcknowledge(this, mCurrentOut->OrigLength()), |
4205 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
4206 | } else { |
4207 | return NS_ERROR_UNEXPECTED; |
4208 | } |
4209 | } |
4210 | DeleteCurrentOutGoingMessage(); |
4211 | PrimeNewOutgoingMessage(); |
4212 | } else { |
4213 | mCurrentOutSent += amtSent; |
4214 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4215 | } |
4216 | } |
4217 | } |
4218 | |
4219 | if (mReleaseOnTransmit) ReleaseSession(); |
4220 | return NS_OK; |
4221 | } |
4222 | |
4223 | // nsIStreamListener |
4224 | |
4225 | NS_IMETHODIMPnsresult |
4226 | WebSocketChannel::OnDataAvailable(nsIRequest* aRequest, |
4227 | nsIInputStream* aInputStream, |
4228 | uint64_t aOffset, uint32_t aCount) { |
4229 | LOG(("WebSocketChannel::OnDataAvailable() %p [%p %p %p %" PRIu64 " %u]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable() %p [%p %p %p %" "l" "u" " %u]\n", this, aRequest, mHttpChannel.get(), aInputStream , aOffset, aCount); } } while (0) |
4230 | this, aRequest, mHttpChannel.get(), aInputStream, aOffset, aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable() %p [%p %p %p %" "l" "u" " %u]\n", this, aRequest, mHttpChannel.get(), aInputStream , aOffset, aCount); } } while (0); |
4231 | |
4232 | // This is the HTTP OnDataAvailable Method, which means this is http data in |
4233 | // response to the upgrade request and there should be no http response body |
4234 | // if the upgrade succeeded. This generally should be caught by a non 101 |
4235 | // response code in OnStartRequest().. so we can ignore the data here |
4236 | |
4237 | LOG(("WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n" , aCount); } } while (0) |
4238 | aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::OnDataAvailable: HTTP data unexpected len>=%u\n" , aCount); } } while (0); |
4239 | |
4240 | return NS_OK; |
4241 | } |
4242 | |
4243 | void WebSocketChannel::DoEnqueueOutgoingMessage() { |
4244 | LOG(("WebSocketChannel::DoEnqueueOutgoingMessage() %p\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage() %p\n" , this); } } while (0); |
4245 | MOZ_ASSERT(mIOThread->IsOnCurrentThread(), "not on right thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIOThread->IsOnCurrentThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIOThread->IsOnCurrentThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mIOThread->IsOnCurrentThread()" " (" "not on right thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 4245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4245; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4246 | |
4247 | if (!mCurrentOut) { |
4248 | PrimeNewOutgoingMessage(); |
4249 | } |
4250 | |
4251 | while (mCurrentOut && mConnection) { |
4252 | nsresult rv = NS_OK; |
4253 | if (mCurrentOut->Length() - mCurrentOutSent == 0) { |
4254 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0) |
4255 | ("WebSocketChannel::DoEnqueueOutgoingMessage: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0) |
4256 | "Try to send %u of hdr/copybreak\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0) |
4257 | mHdrOutToSend))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr/copybreak\n", mHdrOutToSend); } } while (0); |
4258 | rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, nullptr, 0); |
4259 | } else { |
4260 | LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0) |
4261 | ("WebSocketChannel::DoEnqueueOutgoingMessage: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0) |
4262 | "Try to send %u of hdr and %u of data\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0) |
4263 | mHdrOutToSend, mCurrentOut->Length()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: " "Try to send %u of hdr and %u of data\n", mHdrOutToSend, mCurrentOut ->Length()); } } while (0); |
4264 | rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, |
4265 | (uint8_t*)mCurrentOut->BeginReading(), |
4266 | mCurrentOut->Length()); |
4267 | } |
4268 | |
4269 | LOG(("WebSocketChannel::DoEnqueueOutgoingMessage: rv %" PRIx32 "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: rv %" "x" "\n", static_cast<uint32_t>(rv)); } } while (0) |
4270 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla:: detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WebSocketChannel::DoEnqueueOutgoingMessage: rv %" "x" "\n", static_cast<uint32_t>(rv)); } } while (0); |
4271 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4272 | AbortSession(rv); |
4273 | return; |
4274 | } |
4275 | |
4276 | if (!mStopped) { |
4277 | // TODO: Currently, we assume that data is completely written to the |
4278 | // socket after sending it to socket process, but it's not true. The data |
4279 | // could be queued in socket process and waiting for the socket to be able |
4280 | // to write. We should implement flow control for this in bug 1726552. |
4281 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
4282 | target->Dispatch(new CallAcknowledge(this, mCurrentOut->OrigLength()), |
4283 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
4284 | } else { |
4285 | AbortSession(NS_ERROR_UNEXPECTED); |
4286 | return; |
4287 | } |
4288 | } |
4289 | DeleteCurrentOutGoingMessage(); |
4290 | PrimeNewOutgoingMessage(); |
4291 | } |
4292 | |
4293 | if (mReleaseOnTransmit) { |
4294 | ReleaseSession(); |
4295 | } |
4296 | } |
4297 | |
4298 | void WebSocketChannel::OnError(nsresult aStatus) { AbortSession(aStatus); } |
4299 | |
4300 | void WebSocketChannel::OnTCPClosed() { mTCPClosed = true; } |
4301 | |
4302 | nsresult WebSocketChannel::OnDataReceived(uint8_t* aData, uint32_t aCount) { |
4303 | return ProcessInput(aData, aCount); |
4304 | } |
4305 | |
4306 | } // namespace mozilla::net |
4307 | |
4308 | #undef CLOSE_GOING_AWAY |