File: | var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp |
Warning: | line 2678, 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 | mAllowPMCE(1), |
1189 | mPingOutstanding(0), |
1190 | mReleaseOnTransmit(0), |
1191 | mDataStarted(false), |
1192 | mRequestedClose(false), |
1193 | mClientClosed(false), |
1194 | mServerClosed(false), |
1195 | mStopped(false), |
1196 | mCalledOnStop(false), |
1197 | mTCPClosed(false), |
1198 | mOpenedHttpChannel(false), |
1199 | mIncrementedSessionCount(false), |
1200 | mDecrementedSessionCount(false), |
1201 | mMaxMessageSize(INT32_MAX(2147483647)), |
1202 | mStopOnClose(NS_OK), |
1203 | mServerCloseCode(CLOSE_ABNORMAL), |
1204 | mScriptCloseCode(0), |
1205 | mFragmentOpcode(nsIWebSocketFrame::OPCODE_CONTINUATION), |
1206 | mFragmentAccumulator(0), |
1207 | mBuffered(0), |
1208 | mBufferSize(kIncomingBufferInitialSize), |
1209 | mCurrentOut(nullptr), |
1210 | mCurrentOutSent(0), |
1211 | mHdrOutToSend(0), |
1212 | mHdrOut(nullptr), |
1213 | mCompressorMutex("WebSocketChannel::mCompressorMutex"), |
1214 | mDynamicOutputSize(0), |
1215 | mDynamicOutput(nullptr), |
1216 | mPrivateBrowsing(false), |
1217 | mConnectionLogService(nullptr), |
1218 | mMutex("WebSocketChannel::mMutex") { |
1219 | 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" , 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1219; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1220 | |
1221 | 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); |
1222 | |
1223 | nsWSAdmissionManager::Init(); |
1224 | |
1225 | mFramePtr = mBuffer = static_cast<uint8_t*>(moz_xmalloc(mBufferSize)); |
1226 | |
1227 | nsresult rv; |
1228 | mConnectionLogService = mozilla::components::Dashboard::Service(&rv); |
1229 | 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); |
1230 | |
1231 | mService = WebSocketEventService::GetOrCreate(); |
1232 | } |
1233 | |
1234 | WebSocketChannel::~WebSocketChannel() { |
1235 | 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); |
1236 | |
1237 | if (mWasOpened) { |
1238 | 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" , 1238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCalledOnStop" ") (" "WebSocket was opened but OnStop was not called" ")"); do { *((volatile int*)__null) = 1238; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1239 | 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" , 1239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") (" "WebSocket was opened but never stopped" ")"); do { *((volatile int*)__null) = 1239; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1240 | } |
1241 | 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" , 1241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ") (" "DNS/Proxy Request still alive at destruction" ")"); do { *((volatile int*)__null) = 1241; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
1242 | 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" , 1242); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnecting" ") (" "Should not be connecting in destructor" ")"); do { *( (volatile int*)__null) = 1242; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
1243 | |
1244 | free(mBuffer); |
1245 | free(mDynamicOutput); |
1246 | delete mCurrentOut; |
1247 | |
1248 | while ((mCurrentOut = mOutgoingPingMessages.PopFront())) { |
1249 | delete mCurrentOut; |
1250 | } |
1251 | while ((mCurrentOut = mOutgoingPongMessages.PopFront())) { |
1252 | delete mCurrentOut; |
1253 | } |
1254 | while ((mCurrentOut = mOutgoingMessages.PopFront())) { |
1255 | delete mCurrentOut; |
1256 | } |
1257 | |
1258 | mListenerMT = nullptr; |
1259 | |
1260 | NS_ReleaseOnMainThread("WebSocketChannel::mService", mService.forget()); |
1261 | } |
1262 | |
1263 | NS_IMETHODIMPnsresult |
1264 | WebSocketChannel::Observe(nsISupports* subject, const char* topic, |
1265 | const char16_t* data) { |
1266 | 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); |
1267 | |
1268 | if (strcmp(topic, NS_NETWORK_LINK_TOPIC"network:link-status-changed") == 0) { |
1269 | nsCString converted = NS_ConvertUTF16toUTF8(data); |
1270 | const char* state = converted.get(); |
1271 | |
1272 | if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED"changed") == 0) { |
1273 | 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); |
1274 | |
1275 | if (!mIOThread) { |
1276 | // there has not been an asyncopen yet on the object and then we need |
1277 | // no ping. |
1278 | 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); |
1279 | } else { |
1280 | mIOThread->Dispatch( |
1281 | NewRunnableMethod("net::WebSocketChannel::OnNetworkChanged", this, |
1282 | &WebSocketChannel::OnNetworkChanged), |
1283 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1284 | } |
1285 | } |
1286 | } |
1287 | |
1288 | return NS_OK; |
1289 | } |
1290 | |
1291 | nsresult WebSocketChannel::OnNetworkChanged() { |
1292 | if (!mDataStarted) { |
1293 | 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); |
1294 | return NS_OK; |
1295 | } |
1296 | |
1297 | 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" , 1297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1297; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1298 | |
1299 | 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); |
1300 | |
1301 | if (mPingOutstanding) { |
1302 | // If there's an outstanding ping that's expected to get a pong back |
1303 | // we let that do its thing. |
1304 | 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); |
1305 | return NS_OK; |
1306 | } |
1307 | |
1308 | if (mPingForced) { |
1309 | // avoid more than one |
1310 | 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); |
1311 | return NS_OK; |
1312 | } |
1313 | |
1314 | 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); |
1315 | |
1316 | if (!mPingTimer) { |
1317 | // The ping timer is only conditionally running already. If it wasn't |
1318 | // already created do it here. |
1319 | mPingTimer = NS_NewTimer(); |
1320 | if (!mPingTimer) { |
1321 | 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); |
1322 | 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" , 1322); |
1323 | return NS_ERROR_OUT_OF_MEMORY; |
1324 | } |
1325 | } |
1326 | // Trigger the ping timeout asap to fire off a new ping. Wait just |
1327 | // a little bit to better avoid multi-triggers. |
1328 | mPingForced = true; |
1329 | mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT); |
1330 | |
1331 | return NS_OK; |
1332 | } |
1333 | |
1334 | void WebSocketChannel::Shutdown() { nsWSAdmissionManager::Shutdown(); } |
1335 | |
1336 | void WebSocketChannel::GetEffectiveURL(nsAString& aEffectiveURL) const { |
1337 | aEffectiveURL = mEffectiveURL; |
1338 | } |
1339 | |
1340 | bool WebSocketChannel::IsEncrypted() const { return mEncrypted; } |
1341 | |
1342 | void WebSocketChannel::BeginOpen(bool aCalledFromAdmissionManager) { |
1343 | 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" , 1343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1343; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1344 | |
1345 | 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); |
1346 | |
1347 | // Important that we set CONNECTING_IN_PROGRESS before any call to |
1348 | // AbortSession here: ensures that any remaining queued connection(s) are |
1349 | // scheduled in OnStopSession |
1350 | 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); |
1351 | mConnecting = CONNECTING_IN_PROGRESS; |
1352 | |
1353 | if (aCalledFromAdmissionManager) { |
1354 | // When called from nsWSAdmissionManager post an event to avoid potential |
1355 | // re-entering of nsWSAdmissionManager and its lock. |
1356 | NS_DispatchToMainThread( |
1357 | NewRunnableMethod("net::WebSocketChannel::BeginOpenInternal", this, |
1358 | &WebSocketChannel::BeginOpenInternal), |
1359 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1360 | } else { |
1361 | BeginOpenInternal(); |
1362 | } |
1363 | } |
1364 | |
1365 | // MainThread |
1366 | void WebSocketChannel::BeginOpenInternal() { |
1367 | 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); |
1368 | 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" , 1368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 1368; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1369 | |
1370 | nsresult rv; |
1371 | |
1372 | if (mRedirectCallback) { |
1373 | 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); |
1374 | rv = mRedirectCallback->OnRedirectVerifyCallback(NS_OK); |
1375 | mRedirectCallback = nullptr; |
1376 | return; |
1377 | } |
1378 | |
1379 | nsCOMPtr<nsIChannel> localChannel = do_QueryInterface(mChannel, &rv); |
1380 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1381 | 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); |
1382 | AbortSession(NS_ERROR_UNEXPECTED); |
1383 | return; |
1384 | } |
1385 | |
1386 | rv = localChannel->AsyncOpen(this); |
1387 | |
1388 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1389 | 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); |
1390 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
1391 | return; |
1392 | } |
1393 | mOpenedHttpChannel = true; |
1394 | |
1395 | rv = NS_NewTimerWithCallback(getter_AddRefs(mOpenTimer), this, mOpenTimeout, |
1396 | nsITimer::TYPE_ONE_SHOT); |
1397 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1398 | 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) |
1399 | ("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) |
1400 | "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); |
1401 | AbortSession(NS_ERROR_UNEXPECTED); |
1402 | return; |
1403 | } |
1404 | } |
1405 | |
1406 | bool WebSocketChannel::IsPersistentFramePtr() { |
1407 | return (mFramePtr >= mBuffer && mFramePtr < mBuffer + mBufferSize); |
1408 | } |
1409 | |
1410 | // Extends the internal buffer by count and returns the total |
1411 | // amount of data available for read |
1412 | // |
1413 | // Accumulated fragment size is passed in instead of using the member |
1414 | // variable beacuse when transitioning from the stack to the persistent |
1415 | // read buffer we want to explicitly include them in the buffer instead |
1416 | // of as already existing data. |
1417 | bool WebSocketChannel::UpdateReadBuffer(uint8_t* buffer, uint32_t count, |
1418 | uint32_t accumulatedFragments, |
1419 | uint32_t* available) { |
1420 | 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) |
1421 | 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); |
1422 | |
1423 | if (!mBuffered) mFramePtr = mBuffer; |
1424 | |
1425 | 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" , 1425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPersistentFramePtr()" ") (" "update read buffer bad mFramePtr" ")"); do { *((volatile int*)__null) = 1425; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1426 | 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" , 1427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer" ") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null ) = 1427; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
1427 | "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" , 1427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr - accumulatedFragments >= mBuffer" ") (" "reserved FramePtr bad" ")"); do { *((volatile int*)__null ) = 1427; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1428 | |
1429 | if (mBuffered + count <= mBufferSize) { |
1430 | // append to existing buffer |
1431 | 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); |
1432 | } else if (mBuffered + count - (mFramePtr - accumulatedFragments - mBuffer) <= |
1433 | mBufferSize) { |
1434 | // make room in existing buffer by shifting unused data to start |
1435 | mBuffered -= (mFramePtr - mBuffer - accumulatedFragments); |
1436 | 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); |
1437 | ::memmove(mBuffer, mFramePtr - accumulatedFragments, mBuffered); |
1438 | mFramePtr = mBuffer + accumulatedFragments; |
1439 | } else { |
1440 | // existing buffer is not sufficient, extend it |
1441 | mBufferSize += count + 8192 + mBufferSize / 3; |
1442 | 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); |
1443 | uint8_t* old = mBuffer; |
1444 | mBuffer = (uint8_t*)realloc(mBuffer, mBufferSize); |
1445 | if (!mBuffer) { |
1446 | mBuffer = old; |
1447 | return false; |
1448 | } |
1449 | mFramePtr = mBuffer + (mFramePtr - old); |
1450 | } |
1451 | |
1452 | ::memcpy(mBuffer + mBuffered, buffer, count); |
1453 | mBuffered += count; |
1454 | |
1455 | if (available) *available = mBuffered - (mFramePtr - mBuffer); |
1456 | |
1457 | return true; |
1458 | } |
1459 | |
1460 | nsresult WebSocketChannel::ProcessInput(uint8_t* buffer, uint32_t count) { |
1461 | 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); |
1462 | 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" , 1462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1462; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1463 | |
1464 | nsresult rv; |
1465 | |
1466 | // The purpose of ping/pong is to actively probe the peer so that an |
1467 | // unreachable peer is not mistaken for a period of idleness. This |
1468 | // implementation accepts any application level read activity as a sign of |
1469 | // life, it does not necessarily have to be a pong. |
1470 | ResetPingTimer(); |
1471 | |
1472 | uint32_t avail; |
1473 | |
1474 | if (!mBuffered) { |
1475 | // Most of the time we can process right off the stack buffer without |
1476 | // having to accumulate anything |
1477 | mFramePtr = buffer; |
1478 | avail = count; |
1479 | } else { |
1480 | if (!UpdateReadBuffer(buffer, count, mFragmentAccumulator, &avail)) { |
1481 | return NS_ERROR_FILE_TOO_BIG; |
1482 | } |
1483 | } |
1484 | |
1485 | uint8_t* payload; |
1486 | uint32_t totalAvail = avail; |
1487 | |
1488 | while (avail >= 2) { |
1489 | int64_t payloadLength64 = mFramePtr[1] & kPayloadLengthBitsMask; |
1490 | uint8_t finBit = mFramePtr[0] & kFinalFragBit; |
1491 | uint8_t rsvBits = mFramePtr[0] & kRsvBitsMask; |
1492 | uint8_t rsvBit1 = mFramePtr[0] & kRsv1Bit; |
1493 | uint8_t rsvBit2 = mFramePtr[0] & kRsv2Bit; |
1494 | uint8_t rsvBit3 = mFramePtr[0] & kRsv3Bit; |
1495 | uint8_t opcode = mFramePtr[0] & kOpcodeBitsMask; |
1496 | uint8_t maskBit = mFramePtr[1] & kMaskBit; |
1497 | uint32_t mask = 0; |
1498 | |
1499 | uint32_t framingLength = 2; |
1500 | if (maskBit) framingLength += 4; |
1501 | |
1502 | if (payloadLength64 < 126) { |
1503 | if (avail < framingLength) break; |
1504 | } else if (payloadLength64 == 126) { |
1505 | // 16 bit length field |
1506 | framingLength += 2; |
1507 | if (avail < framingLength) break; |
1508 | |
1509 | payloadLength64 = mFramePtr[2] << 8 | mFramePtr[3]; |
1510 | |
1511 | if (payloadLength64 < 126) { |
1512 | // Section 5.2 says that the minimal number of bytes MUST |
1513 | // be used to encode the length in all cases |
1514 | 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); |
1515 | return NS_ERROR_ILLEGAL_VALUE; |
1516 | } |
1517 | |
1518 | } else { |
1519 | // 64 bit length |
1520 | framingLength += 8; |
1521 | if (avail < framingLength) break; |
1522 | |
1523 | if (mFramePtr[2] & 0x80) { |
1524 | // Section 4.2 says that the most significant bit MUST be |
1525 | // 0. (i.e. this is really a 63 bit value) |
1526 | 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); |
1527 | return NS_ERROR_ILLEGAL_VALUE; |
1528 | } |
1529 | |
1530 | // copy this in case it is unaligned |
1531 | payloadLength64 = NetworkEndian::readInt64(mFramePtr + 2); |
1532 | |
1533 | if (payloadLength64 <= 0xffff) { |
1534 | // Section 5.2 says that the minimal number of bytes MUST |
1535 | // be used to encode the length in all cases |
1536 | 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); |
1537 | return NS_ERROR_ILLEGAL_VALUE; |
1538 | } |
1539 | } |
1540 | |
1541 | payload = mFramePtr + framingLength; |
1542 | avail -= framingLength; |
1543 | |
1544 | 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) |
1545 | "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__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 | 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); |
1547 | |
1548 | CheckedInt<int64_t> payloadLengthChecked(payloadLength64); |
1549 | payloadLengthChecked += mFragmentAccumulator; |
1550 | if (!payloadLengthChecked.isValid() || |
1551 | payloadLengthChecked.value() > mMaxMessageSize) { |
1552 | return NS_ERROR_FILE_TOO_BIG; |
1553 | } |
1554 | |
1555 | uint32_t payloadLength = static_cast<uint32_t>(payloadLength64); |
1556 | |
1557 | if (avail < payloadLength) break; |
1558 | |
1559 | 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) |
1560 | 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); |
1561 | |
1562 | if (!maskBit && mIsServerSide) { |
1563 | 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) |
1564 | ("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) |
1565 | "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); |
1566 | return NS_ERROR_ILLEGAL_VALUE; |
1567 | } |
1568 | |
1569 | if (maskBit) { |
1570 | if (!mIsServerSide) { |
1571 | // The server should not be allowed to send masked frames to clients. |
1572 | // But we've been allowing it for some time, so this should be |
1573 | // deprecated with care. |
1574 | 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); |
1575 | } |
1576 | |
1577 | mask = NetworkEndian::readUint32(payload - 4); |
1578 | } |
1579 | |
1580 | if (mask) { |
1581 | ApplyMask(mask, payload, payloadLength); |
1582 | } else if (mIsServerSide) { |
1583 | 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) |
1584 | ("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) |
1585 | "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); |
1586 | return NS_ERROR_ILLEGAL_VALUE; |
1587 | } |
1588 | |
1589 | // Control codes are required to have the fin bit set |
1590 | if (!finBit && (opcode & kControlFrameMask)) { |
1591 | 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); |
1592 | return NS_ERROR_ILLEGAL_VALUE; |
1593 | } |
1594 | |
1595 | if (rsvBits) { |
1596 | // PMCE sets RSV1 bit in the first fragment when the non-control frame |
1597 | // is deflated |
1598 | MutexAutoLock lock(mCompressorMutex); |
1599 | if (mPMCECompressor && rsvBits == kRsv1Bit && mFragmentAccumulator == 0 && |
1600 | !(opcode & kControlFrameMask)) { |
1601 | mPMCECompressor->SetMessageDeflated(); |
1602 | 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); |
1603 | } else { |
1604 | 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) |
1605 | 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); |
1606 | return NS_ERROR_ILLEGAL_VALUE; |
1607 | } |
1608 | } |
1609 | |
1610 | if (!finBit || opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1611 | // This is part of a fragment response |
1612 | |
1613 | // Only the first frame has a non zero op code: Make sure we don't see a |
1614 | // first frame while some old fragments are open |
1615 | if ((mFragmentAccumulator != 0) && |
1616 | (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION)) { |
1617 | 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); |
1618 | return NS_ERROR_ILLEGAL_VALUE; |
1619 | } |
1620 | |
1621 | 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) |
1622 | 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); |
1623 | |
1624 | if (opcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1625 | // Make sure this continuation fragment isn't the first fragment |
1626 | if (mFragmentOpcode == nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1627 | 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); |
1628 | return NS_ERROR_ILLEGAL_VALUE; |
1629 | } |
1630 | |
1631 | // For frag > 1 move the data body back on top of the headers |
1632 | // so we have contiguous stream of data |
1633 | 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" , 1634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1634; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
1634 | "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" , 1634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1634; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1635 | ::memmove(mFramePtr, payload, avail); |
1636 | payload = mFramePtr; |
1637 | if (mBuffered) mBuffered -= framingLength; |
1638 | } else { |
1639 | mFragmentOpcode = opcode; |
1640 | } |
1641 | |
1642 | if (finBit) { |
1643 | 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); |
1644 | payload -= mFragmentAccumulator; |
1645 | payloadLength += mFragmentAccumulator; |
1646 | avail += mFragmentAccumulator; |
1647 | mFragmentAccumulator = 0; |
1648 | opcode = mFragmentOpcode; |
1649 | // reset to detect if next message illegally starts with continuation |
1650 | mFragmentOpcode = nsIWebSocketFrame::OPCODE_CONTINUATION; |
1651 | } else { |
1652 | opcode = nsIWebSocketFrame::OPCODE_CONTINUATION; |
1653 | mFragmentAccumulator += payloadLength; |
1654 | } |
1655 | } else if (mFragmentAccumulator != 0 && !(opcode & kControlFrameMask)) { |
1656 | // This frame is not part of a fragment sequence but we |
1657 | // have an open fragment.. it must be a control code or else |
1658 | // we have a problem |
1659 | 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); |
1660 | return NS_ERROR_ILLEGAL_VALUE; |
1661 | } |
1662 | |
1663 | if (mServerClosed) { |
1664 | 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) |
1665 | 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); |
1666 | // nop |
1667 | } else if (mStopped) { |
1668 | 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) |
1669 | 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); |
1670 | } else if (opcode == nsIWebSocketFrame::OPCODE_TEXT) { |
1671 | if (mListenerMT) { |
1672 | nsCString utf8Data; |
1673 | { |
1674 | MutexAutoLock lock(mCompressorMutex); |
1675 | bool isDeflated = |
1676 | mPMCECompressor && mPMCECompressor->IsMessageDeflated(); |
1677 | 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) |
1678 | 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); |
1679 | |
1680 | if (isDeflated) { |
1681 | rv = mPMCECompressor->Inflate(payload, payloadLength, utf8Data); |
1682 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1683 | return rv; |
1684 | } |
1685 | 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) |
1686 | ("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) |
1687 | "[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) |
1688 | 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); |
1689 | } else { |
1690 | if (!utf8Data.Assign((const char*)payload, payloadLength, |
1691 | mozilla::fallible)) { |
1692 | return NS_ERROR_OUT_OF_MEMORY; |
1693 | } |
1694 | } |
1695 | } |
1696 | |
1697 | // Section 8.1 says to fail connection if invalid utf-8 in text message |
1698 | if (!IsUtf8(utf8Data)) { |
1699 | 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); |
1700 | return NS_ERROR_CANNOT_CONVERT_DATA; |
1701 | } |
1702 | |
1703 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
1704 | finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, utf8Data); |
1705 | |
1706 | if (frame) { |
1707 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1708 | } |
1709 | |
1710 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1711 | target->Dispatch(new CallOnMessageAvailable(this, utf8Data, -1), |
1712 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1713 | } else { |
1714 | return NS_ERROR_UNEXPECTED; |
1715 | } |
1716 | if (mConnectionLogService && !mPrivateBrowsing) { |
1717 | mConnectionLogService->NewMsgReceived(mHost, mSerial, count); |
1718 | 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); |
1719 | } |
1720 | } |
1721 | } else if (opcode & kControlFrameMask) { |
1722 | // control frames |
1723 | if (payloadLength > 125) { |
1724 | 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) |
1725 | 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); |
1726 | return NS_ERROR_ILLEGAL_VALUE; |
1727 | } |
1728 | |
1729 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
1730 | finBit, rsvBit1, rsvBit2, rsvBit3, opcode, maskBit, mask, payload, |
1731 | payloadLength); |
1732 | |
1733 | if (opcode == nsIWebSocketFrame::OPCODE_CLOSE) { |
1734 | 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); |
1735 | mServerClosed = true; |
1736 | |
1737 | mServerCloseCode = CLOSE_NO_STATUS; |
1738 | if (payloadLength >= 2) { |
1739 | mServerCloseCode = NetworkEndian::readUint16(payload); |
1740 | 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); |
1741 | uint16_t msglen = static_cast<uint16_t>(payloadLength - 2); |
1742 | if (msglen > 0) { |
1743 | mServerCloseReason.SetLength(msglen); |
1744 | memcpy(mServerCloseReason.BeginWriting(), (const char*)payload + 2, |
1745 | msglen); |
1746 | |
1747 | // section 8.1 says to replace received non utf-8 sequences |
1748 | // (which are non-conformant to send) with u+fffd, |
1749 | // but secteam feels that silently rewriting messages is |
1750 | // inappropriate - so we will fail the connection instead. |
1751 | if (!IsUtf8(mServerCloseReason)) { |
1752 | 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); |
1753 | return NS_ERROR_CANNOT_CONVERT_DATA; |
1754 | } |
1755 | |
1756 | 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) |
1757 | 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); |
1758 | } |
1759 | } |
1760 | |
1761 | if (mCloseTimer) { |
1762 | mCloseTimer->Cancel(); |
1763 | mCloseTimer = nullptr; |
1764 | } |
1765 | |
1766 | if (frame) { |
1767 | // We send the frame immediately becuase we want to have it dispatched |
1768 | // before the CallOnServerClose. |
1769 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1770 | frame = nullptr; |
1771 | } |
1772 | |
1773 | if (mListenerMT) { |
1774 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1775 | target->Dispatch(new CallOnServerClose(this, mServerCloseCode, |
1776 | mServerCloseReason), |
1777 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1778 | } else { |
1779 | return NS_ERROR_UNEXPECTED; |
1780 | } |
1781 | } |
1782 | |
1783 | if (mClientClosed) ReleaseSession(); |
1784 | } else if (opcode == nsIWebSocketFrame::OPCODE_PING) { |
1785 | 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); |
1786 | GeneratePong(payload, payloadLength); |
1787 | } else if (opcode == nsIWebSocketFrame::OPCODE_PONG) { |
1788 | // opcode OPCODE_PONG: the mere act of receiving the packet is all we |
1789 | // need to do for the pong to trigger the activity timers |
1790 | 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); |
1791 | } else { |
1792 | /* unknown control frame opcode */ |
1793 | 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); |
1794 | return NS_ERROR_ILLEGAL_VALUE; |
1795 | } |
1796 | |
1797 | if (mFragmentAccumulator) { |
1798 | // Remove the control frame from the stream so we have a contiguous |
1799 | // data buffer of reassembled fragments |
1800 | 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); |
1801 | 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" , 1802); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1802; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
1802 | "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" , 1802); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFramePtr + framingLength == payload" ") (" "payload offset from frameptr wrong" ")"); do { *((volatile int*)__null) = 1802; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
1803 | ::memmove(mFramePtr, payload + payloadLength, avail - payloadLength); |
1804 | payload = mFramePtr; |
1805 | avail -= payloadLength; |
1806 | if (mBuffered) mBuffered -= framingLength + payloadLength; |
1807 | payloadLength = 0; |
1808 | } |
1809 | |
1810 | if (frame) { |
1811 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1812 | } |
1813 | } else if (opcode == nsIWebSocketFrame::OPCODE_BINARY) { |
1814 | if (mListenerMT) { |
1815 | nsCString binaryData; |
1816 | { |
1817 | MutexAutoLock lock(mCompressorMutex); |
1818 | bool isDeflated = |
1819 | mPMCECompressor && mPMCECompressor->IsMessageDeflated(); |
1820 | 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) |
1821 | 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); |
1822 | |
1823 | if (isDeflated) { |
1824 | rv = mPMCECompressor->Inflate(payload, payloadLength, binaryData); |
1825 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1826 | return rv; |
1827 | } |
1828 | 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) |
1829 | ("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) |
1830 | "[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) |
1831 | 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); |
1832 | } else { |
1833 | if (!binaryData.Assign((const char*)payload, payloadLength, |
1834 | mozilla::fallible)) { |
1835 | return NS_ERROR_OUT_OF_MEMORY; |
1836 | } |
1837 | } |
1838 | } |
1839 | |
1840 | RefPtr<WebSocketFrame> frame = |
1841 | mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, |
1842 | opcode, maskBit, mask, binaryData); |
1843 | if (frame) { |
1844 | mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); |
1845 | } |
1846 | |
1847 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
1848 | target->Dispatch( |
1849 | new CallOnMessageAvailable(this, binaryData, binaryData.Length()), |
1850 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
1851 | } else { |
1852 | return NS_ERROR_UNEXPECTED; |
1853 | } |
1854 | // To add the header to 'Networking Dashboard' log |
1855 | if (mConnectionLogService && !mPrivateBrowsing) { |
1856 | mConnectionLogService->NewMsgReceived(mHost, mSerial, count); |
1857 | 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); |
1858 | } |
1859 | } |
1860 | } else if (opcode != nsIWebSocketFrame::OPCODE_CONTINUATION) { |
1861 | /* unknown opcode */ |
1862 | 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); |
1863 | return NS_ERROR_ILLEGAL_VALUE; |
1864 | } |
1865 | |
1866 | mFramePtr = payload + payloadLength; |
1867 | avail -= payloadLength; |
1868 | totalAvail = avail; |
1869 | } |
1870 | |
1871 | // Adjust the stateful buffer. If we were operating off the stack and |
1872 | // now have a partial message then transition to the buffer, or if |
1873 | // we were working off the buffer but no longer have any active state |
1874 | // then transition to the stack |
1875 | if (!IsPersistentFramePtr()) { |
1876 | mBuffered = 0; |
1877 | |
1878 | if (mFragmentAccumulator) { |
1879 | 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); |
1880 | |
1881 | if (!UpdateReadBuffer(mFramePtr - mFragmentAccumulator, |
1882 | totalAvail + mFragmentAccumulator, 0, nullptr)) { |
1883 | return NS_ERROR_FILE_TOO_BIG; |
1884 | } |
1885 | |
1886 | // UpdateReadBuffer will reset the frameptr to the beginning |
1887 | // of new saved state, so we need to skip past processed framgents |
1888 | mFramePtr += mFragmentAccumulator; |
1889 | } else if (totalAvail) { |
1890 | 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); |
1891 | if (!UpdateReadBuffer(mFramePtr, totalAvail, 0, nullptr)) { |
1892 | return NS_ERROR_FILE_TOO_BIG; |
1893 | } |
1894 | } |
1895 | } else if (!mFragmentAccumulator && !totalAvail) { |
1896 | // If we were working off a saved buffer state and there is no partial |
1897 | // frame or fragment in process, then revert to stack behavior |
1898 | 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); |
1899 | mBuffered = 0; |
1900 | |
1901 | // release memory if we've been processing a large message |
1902 | if (mBufferSize > kIncomingBufferStableSize) { |
1903 | mBufferSize = kIncomingBufferStableSize; |
1904 | free(mBuffer); |
1905 | mBuffer = (uint8_t*)moz_xmalloc(mBufferSize); |
1906 | } |
1907 | } |
1908 | return NS_OK; |
1909 | } |
1910 | |
1911 | /* static */ |
1912 | void WebSocketChannel::ApplyMask(uint32_t mask, uint8_t* data, uint64_t len) { |
1913 | if (!data || len == 0) return; |
1914 | |
1915 | // Optimally we want to apply the mask 32 bits at a time, |
1916 | // but the buffer might not be alligned. So we first deal with |
1917 | // 0 to 3 bytes of preamble individually |
1918 | |
1919 | while (len && (reinterpret_cast<uintptr_t>(data) & 3)) { |
1920 | *data ^= mask >> 24; |
1921 | mask = RotateLeft(mask, 8); |
1922 | data++; |
1923 | len--; |
1924 | } |
1925 | |
1926 | // perform mask on full words of data |
1927 | |
1928 | uint32_t* iData = (uint32_t*)data; |
1929 | uint32_t* end = iData + (len / 4); |
1930 | NetworkEndian::writeUint32(&mask, mask); |
1931 | for (; iData < end; iData++) *iData ^= mask; |
1932 | mask = NetworkEndian::readUint32(&mask); |
1933 | data = (uint8_t*)iData; |
1934 | len = len % 4; |
1935 | |
1936 | // There maybe up to 3 trailing bytes that need to be dealt with |
1937 | // individually |
1938 | |
1939 | while (len) { |
1940 | *data ^= mask >> 24; |
1941 | mask = RotateLeft(mask, 8); |
1942 | data++; |
1943 | len--; |
1944 | } |
1945 | } |
1946 | |
1947 | void WebSocketChannel::GeneratePing() { |
1948 | nsAutoCString buf; |
1949 | buf.AssignLiteral("PING"); |
1950 | EnqueueOutgoingMessage(mOutgoingPingMessages, |
1951 | new OutboundMessage(kMsgTypePing, buf)); |
1952 | } |
1953 | |
1954 | void WebSocketChannel::GeneratePong(uint8_t* payload, uint32_t len) { |
1955 | nsAutoCString buf; |
1956 | buf.SetLength(len); |
1957 | if (buf.Length() < len) { |
1958 | 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); |
1959 | return; |
1960 | } |
1961 | |
1962 | memcpy(buf.BeginWriting(), payload, len); |
1963 | EnqueueOutgoingMessage(mOutgoingPongMessages, |
1964 | new OutboundMessage(kMsgTypePong, buf)); |
1965 | } |
1966 | |
1967 | void WebSocketChannel::EnqueueOutgoingMessage(nsDeque<OutboundMessage>& aQueue, |
1968 | OutboundMessage* aMsg) { |
1969 | 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" , 1969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 1969; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
1970 | |
1971 | 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) |
1972 | ("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) |
1973 | "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) |
1974 | 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); |
1975 | |
1976 | aQueue.Push(aMsg); |
1977 | if (mSocketOut) { |
1978 | OnOutputStreamReady(mSocketOut); |
1979 | } else { |
1980 | DoEnqueueOutgoingMessage(); |
1981 | } |
1982 | } |
1983 | |
1984 | uint16_t WebSocketChannel::ResultToCloseCode(nsresult resultCode) { |
1985 | if (NS_SUCCEEDED(resultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(resultCode)), 1)) )) return CLOSE_NORMAL; |
1986 | |
1987 | switch (resultCode) { |
1988 | case NS_ERROR_FILE_TOO_BIG: |
1989 | case NS_ERROR_OUT_OF_MEMORY: |
1990 | return CLOSE_TOO_LARGE; |
1991 | case NS_ERROR_CANNOT_CONVERT_DATA: |
1992 | return CLOSE_INVALID_PAYLOAD; |
1993 | case NS_ERROR_UNEXPECTED: |
1994 | return CLOSE_INTERNAL_ERROR; |
1995 | default: |
1996 | return CLOSE_PROTOCOL_ERROR; |
1997 | } |
1998 | } |
1999 | |
2000 | void WebSocketChannel::PrimeNewOutgoingMessage() { |
2001 | 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); |
2002 | 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" , 2002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 2002; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2003 | 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" , 2003); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCurrentOut" ") (" "Current message in progress" ")"); do { *((volatile int *)__null) = 2003; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2004 | |
2005 | nsresult rv = NS_OK; |
2006 | |
2007 | mCurrentOut = mOutgoingPongMessages.PopFront(); |
2008 | if (mCurrentOut) { |
2009 | 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" , 2009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePong" ") (" "Not pong message!" ")"); do { *((volatile int*)__null ) = 2009; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2010 | } else { |
2011 | mCurrentOut = mOutgoingPingMessages.PopFront(); |
2012 | if (mCurrentOut) { |
2013 | 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" , 2014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing" ") (" "Not ping message!" ")"); do { *((volatile int*)__null ) = 2014; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
2014 | "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" , 2014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentOut->GetMsgType() == kMsgTypePing" ") (" "Not ping message!" ")"); do { *((volatile int*)__null ) = 2014; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2015 | } else { |
2016 | mCurrentOut = mOutgoingMessages.PopFront(); |
2017 | } |
2018 | } |
2019 | |
2020 | if (!mCurrentOut) return; |
2021 | |
2022 | auto cleanupAfterFailure = |
2023 | MakeScopeExit([&] { DeleteCurrentOutGoingMessage(); }); |
2024 | |
2025 | WsMsgType msgType = mCurrentOut->GetMsgType(); |
2026 | |
2027 | 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) |
2028 | ("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) |
2029 | "%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) |
2030 | 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); |
2031 | |
2032 | mCurrentOutSent = 0; |
2033 | mHdrOut = mOutHeader; |
2034 | |
2035 | uint8_t maskBit = mIsServerSide ? 0 : kMaskBit; |
2036 | uint8_t maskSize = mIsServerSide ? 0 : 4; |
2037 | |
2038 | uint8_t* payload = nullptr; |
2039 | |
2040 | if (msgType == kMsgTypeFin) { |
2041 | // This is a demand to create a close message |
2042 | if (mClientClosed) { |
2043 | DeleteCurrentOutGoingMessage(); |
2044 | PrimeNewOutgoingMessage(); |
2045 | cleanupAfterFailure.release(); |
2046 | return; |
2047 | } |
2048 | |
2049 | mClientClosed = true; |
2050 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_CLOSE; |
2051 | mOutHeader[1] = maskBit; |
2052 | |
2053 | // payload is offset 2 plus size of the mask |
2054 | payload = mOutHeader + 2 + maskSize; |
2055 | |
2056 | // The close reason code sits in the first 2 bytes of payload |
2057 | // If the channel user provided a code and reason during Close() |
2058 | // and there isn't an internal error, use that. |
2059 | if (NS_SUCCEEDED(mStopOnClose)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStopOnClose)), 1 )))) { |
2060 | MutexAutoLock lock(mMutex); |
2061 | if (mScriptCloseCode) { |
2062 | NetworkEndian::writeUint16(payload, mScriptCloseCode); |
2063 | mOutHeader[1] += 2; |
2064 | mHdrOutToSend = 4 + maskSize; |
2065 | if (!mScriptCloseReason.IsEmpty()) { |
2066 | 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" , 2067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123" ") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null ) = 2067; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false) |
2067 | "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" , 2067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptCloseReason.Length() <= 123" ") (" "Close Reason Too Long" ")"); do { *((volatile int*)__null ) = 2067; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2068 | mOutHeader[1] += mScriptCloseReason.Length(); |
2069 | mHdrOutToSend += mScriptCloseReason.Length(); |
2070 | memcpy(payload + 2, mScriptCloseReason.BeginReading(), |
2071 | mScriptCloseReason.Length()); |
2072 | } |
2073 | } else { |
2074 | // No close code/reason, so payload length = 0. We must still send mask |
2075 | // even though it's not used. Keep payload offset so we write mask |
2076 | // below. |
2077 | mHdrOutToSend = 2 + maskSize; |
2078 | } |
2079 | } else { |
2080 | NetworkEndian::writeUint16(payload, ResultToCloseCode(mStopOnClose)); |
2081 | mOutHeader[1] += 2; |
2082 | mHdrOutToSend = 4 + maskSize; |
2083 | } |
2084 | |
2085 | if (mServerClosed) { |
2086 | /* bidi close complete */ |
2087 | mReleaseOnTransmit = 1; |
2088 | } else if (NS_FAILED(mStopOnClose)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStopOnClose)), 0) ))) { |
2089 | /* result of abort session - give up */ |
2090 | StopSession(mStopOnClose); |
2091 | } else { |
2092 | /* wait for reciprocal close from server */ |
2093 | rv = NS_NewTimerWithCallback(getter_AddRefs(mCloseTimer), this, |
2094 | mCloseTimeout, nsITimer::TYPE_ONE_SHOT); |
2095 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2096 | StopSession(rv); |
2097 | } |
2098 | } |
2099 | } else { |
2100 | switch (msgType) { |
2101 | case kMsgTypePong: |
2102 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PONG; |
2103 | break; |
2104 | case kMsgTypePing: |
2105 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PING; |
2106 | break; |
2107 | case kMsgTypeString: |
2108 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_TEXT; |
2109 | break; |
2110 | case kMsgTypeStream: |
2111 | // HACK ALERT: read in entire stream into string. |
2112 | // Will block socket transport thread if file is blocking. |
2113 | // TODO: bug 704447: don't block socket thread! |
2114 | rv = mCurrentOut->ConvertStreamToString(); |
2115 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2116 | AbortSession(NS_ERROR_FILE_TOO_BIG); |
2117 | return; |
2118 | } |
2119 | // Now we're a binary string |
2120 | msgType = kMsgTypeBinaryString; |
2121 | |
2122 | // no break: fall down into binary string case |
2123 | [[fallthrough]]; |
2124 | |
2125 | case kMsgTypeBinaryString: |
2126 | mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_BINARY; |
2127 | break; |
2128 | case kMsgTypeFin: |
2129 | 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" , 2129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "unreachable" ")"); do { *((volatile int*)__null) = 2129; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); // avoid compiler warning |
2130 | break; |
2131 | } |
2132 | |
2133 | // deflate the payload if PMCE is negotiated |
2134 | MutexAutoLock lock(mCompressorMutex); |
2135 | if (mPMCECompressor && |
2136 | (msgType == kMsgTypeString || msgType == kMsgTypeBinaryString)) { |
2137 | if (mCurrentOut->DeflatePayload(mPMCECompressor.get())) { |
2138 | // The payload was deflated successfully, set RSV1 bit |
2139 | mOutHeader[0] |= kRsv1Bit; |
2140 | |
2141 | 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) |
2142 | ("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) |
2143 | "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) |
2144 | 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) |
2145 | 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); |
2146 | } |
2147 | } |
2148 | |
2149 | if (mCurrentOut->Length() < 126) { |
2150 | mOutHeader[1] = mCurrentOut->Length() | maskBit; |
2151 | mHdrOutToSend = 2 + maskSize; |
2152 | } else if (mCurrentOut->Length() <= 0xffff) { |
2153 | mOutHeader[1] = 126 | maskBit; |
2154 | NetworkEndian::writeUint16(mOutHeader + sizeof(uint16_t), |
2155 | mCurrentOut->Length()); |
2156 | mHdrOutToSend = 4 + maskSize; |
2157 | } else { |
2158 | mOutHeader[1] = 127 | maskBit; |
2159 | NetworkEndian::writeUint64(mOutHeader + 2, mCurrentOut->Length()); |
2160 | mHdrOutToSend = 10 + maskSize; |
2161 | } |
2162 | payload = mOutHeader + mHdrOutToSend; |
2163 | } |
2164 | |
2165 | 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" , 2165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "payload" ") (" "payload offset not found" ")"); do { *((volatile int*)__null ) = 2165; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2166 | |
2167 | uint32_t mask = 0; |
2168 | if (!mIsServerSide) { |
2169 | // Perform the sending mask. Never use a zero mask |
2170 | do { |
2171 | static_assert(4 == sizeof(mask), "Size of the mask should be equal to 4"); |
2172 | nsresult rv = mRandomGenerator->GenerateRandomBytesInto(mask); |
2173 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2174 | 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) |
2175 | ("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) |
2176 | "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) |
2177 | 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); |
2178 | AbortSession(rv); |
2179 | return; |
2180 | } |
2181 | } while (!mask); |
2182 | NetworkEndian::writeUint32(payload - sizeof(uint32_t), mask); |
2183 | } |
2184 | |
2185 | 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); |
2186 | |
2187 | // We don't mask the framing, but occasionally we stick a little payload |
2188 | // data in the buffer used for the framing. Close frames are the current |
2189 | // example. This data needs to be masked, but it is never more than a |
2190 | // handful of bytes and might rotate the mask, so we can just do it locally. |
2191 | // For real data frames we ship the bulk of the payload off to ApplyMask() |
2192 | |
2193 | RefPtr<WebSocketFrame> frame = mService->CreateFrameIfNeeded( |
2194 | mOutHeader[0] & WebSocketChannel::kFinalFragBit, |
2195 | mOutHeader[0] & WebSocketChannel::kRsv1Bit, |
2196 | mOutHeader[0] & WebSocketChannel::kRsv2Bit, |
2197 | mOutHeader[0] & WebSocketChannel::kRsv3Bit, |
2198 | mOutHeader[0] & WebSocketChannel::kOpcodeBitsMask, |
2199 | mOutHeader[1] & WebSocketChannel::kMaskBit, mask, payload, |
2200 | mHdrOutToSend - (payload - mOutHeader), mCurrentOut->BeginOrigReading(), |
2201 | mCurrentOut->OrigLength()); |
2202 | |
2203 | if (frame) { |
2204 | mService->FrameSent(mSerial, mInnerWindowID, frame.forget()); |
2205 | } |
2206 | |
2207 | if (mask) { |
2208 | while (payload < (mOutHeader + mHdrOutToSend)) { |
2209 | *payload ^= mask >> 24; |
2210 | mask = RotateLeft(mask, 8); |
2211 | payload++; |
2212 | } |
2213 | |
2214 | // Mask the real message payloads |
2215 | ApplyMask(mask, mCurrentOut->BeginWriting(), mCurrentOut->Length()); |
2216 | } |
2217 | |
2218 | int32_t len = mCurrentOut->Length(); |
2219 | |
2220 | // for small frames, copy it all together for a contiguous write |
2221 | if (len && len <= kCopyBreak) { |
2222 | memcpy(mOutHeader + mHdrOutToSend, mCurrentOut->BeginWriting(), len); |
2223 | mHdrOutToSend += len; |
2224 | mCurrentOutSent = len; |
2225 | } |
2226 | |
2227 | // Transmitting begins - mHdrOutToSend bytes from mOutHeader and |
2228 | // mCurrentOut->Length() bytes from mCurrentOut. The latter may be |
2229 | // coaleseced into the former for small messages or as the result of the |
2230 | // compression process. |
2231 | |
2232 | cleanupAfterFailure.release(); |
2233 | } |
2234 | |
2235 | void WebSocketChannel::DeleteCurrentOutGoingMessage() { |
2236 | delete mCurrentOut; |
2237 | mCurrentOut = nullptr; |
2238 | mCurrentOutSent = 0; |
2239 | } |
2240 | |
2241 | void WebSocketChannel::EnsureHdrOut(uint32_t size) { |
2242 | 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); |
2243 | |
2244 | if (mDynamicOutputSize < size) { |
2245 | mDynamicOutputSize = size; |
2246 | mDynamicOutput = (uint8_t*)moz_xrealloc(mDynamicOutput, mDynamicOutputSize); |
2247 | } |
2248 | |
2249 | mHdrOut = mDynamicOutput; |
2250 | } |
2251 | |
2252 | namespace { |
2253 | |
2254 | class RemoveObserverRunnable : public Runnable { |
2255 | RefPtr<WebSocketChannel> mChannel; |
2256 | |
2257 | public: |
2258 | explicit RemoveObserverRunnable(WebSocketChannel* aChannel) |
2259 | : Runnable("net::RemoveObserverRunnable"), mChannel(aChannel) {} |
2260 | |
2261 | NS_IMETHODvirtual nsresult Run() override { |
2262 | nsCOMPtr<nsIObserverService> observerService = |
2263 | mozilla::services::GetObserverService(); |
2264 | if (!observerService) { |
2265 | 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" , 2265); |
2266 | return NS_OK; |
2267 | } |
2268 | |
2269 | observerService->RemoveObserver(mChannel, NS_NETWORK_LINK_TOPIC"network:link-status-changed"); |
2270 | return NS_OK; |
2271 | } |
2272 | }; |
2273 | |
2274 | } // namespace |
2275 | |
2276 | void WebSocketChannel::CleanupConnection() { |
2277 | // normally this should be called on socket thread, but it may be called |
2278 | // on MainThread |
2279 | |
2280 | 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); |
2281 | // This needs to run on the IOThread so we don't need to lock a bunch of these |
2282 | if (!mIOThread->IsOnCurrentThread()) { |
2283 | mIOThread->Dispatch( |
2284 | NewRunnableMethod("net::WebSocketChannel::CleanupConnection", this, |
2285 | &WebSocketChannel::CleanupConnection), |
2286 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2287 | return; |
2288 | } |
2289 | |
2290 | if (mLingeringCloseTimer) { |
2291 | mLingeringCloseTimer->Cancel(); |
2292 | mLingeringCloseTimer = nullptr; |
2293 | } |
2294 | |
2295 | if (mSocketIn) { |
2296 | if (mDataStarted) { |
2297 | mSocketIn->AsyncWait(nullptr, 0, 0, nullptr); |
2298 | } |
2299 | mSocketIn = nullptr; |
2300 | } |
2301 | |
2302 | if (mSocketOut) { |
2303 | mSocketOut->AsyncWait(nullptr, 0, 0, nullptr); |
2304 | mSocketOut = nullptr; |
2305 | } |
2306 | |
2307 | if (mTransport) { |
2308 | mTransport->SetSecurityCallbacks(nullptr); |
2309 | mTransport->SetEventSink(nullptr, nullptr); |
2310 | mTransport->Close(NS_BASE_STREAM_CLOSED); |
2311 | mTransport = nullptr; |
2312 | } |
2313 | |
2314 | if (mConnection) { |
2315 | mConnection->Close(); |
2316 | mConnection = nullptr; |
2317 | } |
2318 | |
2319 | if (mConnectionLogService && !mPrivateBrowsing) { |
2320 | mConnectionLogService->RemoveHost(mHost, mSerial); |
2321 | } |
2322 | |
2323 | // The observer has to be removed on the main-thread. |
2324 | NS_DispatchToMainThread(new RemoveObserverRunnable(this)); |
2325 | |
2326 | DecrementSessionCount(); |
2327 | } |
2328 | |
2329 | void WebSocketChannel::StopSession(nsresult reason) { |
2330 | 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) |
2331 | 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); |
2332 | |
2333 | { |
2334 | MutexAutoLock lock(mMutex); |
2335 | if (mStopped) { |
2336 | return; |
2337 | } |
2338 | mStopped = true; |
2339 | } |
2340 | |
2341 | DoStopSession(reason); |
2342 | } |
2343 | |
2344 | void WebSocketChannel::DoStopSession(nsresult reason) { |
2345 | 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) |
2346 | 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); |
2347 | |
2348 | // normally this should be called on socket thread, but it is ok to call it |
2349 | // from OnStartRequest before the socket thread machine has gotten underway. |
2350 | // If mDataStarted is false, this is called on MainThread for Close(). |
2351 | // Otherwise it should be called on the IO thread |
2352 | |
2353 | 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" , 2353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")" ); do { *((volatile int*)__null) = 2353; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2354 | 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" , 2354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || mTCPClosed || !mDataStarted" ")"); do { *((volatile int*)__null) = 2354; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2355 | |
2356 | if (!mOpenedHttpChannel) { |
2357 | // The HTTP channel information will never be used in this case |
2358 | NS_ReleaseOnMainThread("WebSocketChannel::mChannel", mChannel.forget()); |
2359 | NS_ReleaseOnMainThread("WebSocketChannel::mHttpChannel", |
2360 | mHttpChannel.forget()); |
2361 | NS_ReleaseOnMainThread("WebSocketChannel::mLoadGroup", mLoadGroup.forget()); |
2362 | NS_ReleaseOnMainThread("WebSocketChannel::mCallbacks", mCallbacks.forget()); |
2363 | } |
2364 | |
2365 | if (mCloseTimer) { |
2366 | mCloseTimer->Cancel(); |
2367 | mCloseTimer = nullptr; |
2368 | } |
2369 | |
2370 | // mOpenTimer must be null if mDataStarted is true and we're not on MainThread |
2371 | if (mOpenTimer) { |
2372 | 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" , 2372); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2372; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2373 | mOpenTimer->Cancel(); |
2374 | mOpenTimer = nullptr; |
2375 | } |
2376 | |
2377 | { |
2378 | MutexAutoLock lock(mMutex); |
2379 | if (mReconnectDelayTimer) { |
2380 | mReconnectDelayTimer->Cancel(); |
2381 | NS_ReleaseOnMainThread("WebSocketChannel::mMutex", |
2382 | mReconnectDelayTimer.forget()); |
2383 | } |
2384 | } |
2385 | |
2386 | if (mPingTimer) { |
2387 | mPingTimer->Cancel(); |
2388 | mPingTimer = nullptr; |
2389 | } |
2390 | |
2391 | if (!mTCPClosed && mDataStarted) { |
2392 | if (mSocketIn) { |
2393 | // Drain, within reason, this socket. if we leave any data |
2394 | // unconsumed (including the tcp fin) a RST will be generated |
2395 | // The right thing to do here is shutdown(SHUT_WR) and then wait |
2396 | // a little while to see if any data comes in.. but there is no |
2397 | // reason to delay things for that when the websocket handshake |
2398 | // is supposed to guarantee a quiet connection except for that fin. |
2399 | |
2400 | char buffer[512]; |
2401 | uint32_t count = 0; |
2402 | uint32_t total = 0; |
2403 | nsresult rv; |
2404 | do { |
2405 | total += count; |
2406 | rv = mSocketIn->Read(buffer, 512, &count); |
2407 | if (rv != NS_BASE_STREAM_WOULD_BLOCK && (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || count == 0)) { |
2408 | mTCPClosed = true; |
2409 | } |
2410 | } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && count > 0 && total < 32000); |
2411 | } else if (mConnection) { |
2412 | mConnection->DrainSocketData(); |
2413 | } |
2414 | } |
2415 | |
2416 | int32_t sessionCount = kLingeringCloseThreshold; |
2417 | nsWSAdmissionManager::GetSessionCount(sessionCount); |
2418 | |
2419 | if (!mTCPClosed && (mTransport || mConnection) && |
2420 | sessionCount < kLingeringCloseThreshold) { |
2421 | // 7.1.1 says that the client SHOULD wait for the server to close the TCP |
2422 | // connection. This is so we can reuse port numbers before 2 MSL expires, |
2423 | // which is not really as much of a concern for us as the amount of state |
2424 | // that might be accrued by keeping this channel object around waiting for |
2425 | // the server. We handle the SHOULD by waiting a short time in the common |
2426 | // case, but not waiting in the case of high concurrency. |
2427 | // |
2428 | // Normally this will be taken care of in AbortSession() after mTCPClosed |
2429 | // is set when the server close arrives without waiting for the timeout to |
2430 | // expire. |
2431 | |
2432 | 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); |
2433 | |
2434 | nsresult rv; |
2435 | rv = NS_NewTimerWithCallback(getter_AddRefs(mLingeringCloseTimer), this, |
2436 | kLingeringCloseTimeout, |
2437 | nsITimer::TYPE_ONE_SHOT); |
2438 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CleanupConnection(); |
2439 | } else { |
2440 | CleanupConnection(); |
2441 | } |
2442 | |
2443 | { |
2444 | MutexAutoLock lock(mMutex); |
2445 | if (mCancelable) { |
2446 | mCancelable->Cancel(NS_ERROR_UNEXPECTED); |
2447 | mCancelable = nullptr; |
2448 | } |
2449 | } |
2450 | |
2451 | { |
2452 | MutexAutoLock lock(mCompressorMutex); |
2453 | mPMCECompressor = nullptr; |
2454 | } |
2455 | if (!mCalledOnStop) { |
2456 | mCalledOnStop = true; |
2457 | |
2458 | nsWSAdmissionManager::OnStopSession(this, reason); |
2459 | |
2460 | RefPtr<CallOnStop> runnable = new CallOnStop(this, reason); |
2461 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
2462 | target->Dispatch(runnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2463 | } |
2464 | } |
2465 | } |
2466 | |
2467 | // Called from MainThread, and called from IOThread in |
2468 | // PrimeNewOutgoingMessage |
2469 | void WebSocketChannel::AbortSession(nsresult reason) { |
2470 | 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) |
2471 | "] 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) |
2472 | 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); |
2473 | |
2474 | 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" , 2474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(reason)), 0)))" ") (" "reason must be a failure!" ")"); do { *((volatile int *)__null) = 2474; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2475 | |
2476 | // normally this should be called on socket thread, but it is ok to call it |
2477 | // from the main thread before StartWebsocketData() has completed |
2478 | 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" , 2478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread() || !mDataStarted" ")"); do { *((volatile int*)__null) = 2478; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2479 | |
2480 | // When we are failing we need to close the TCP connection immediately |
2481 | // as per 7.1.1 |
2482 | mTCPClosed = true; |
2483 | |
2484 | if (mLingeringCloseTimer) { |
2485 | 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" , 2485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ") (" "Lingering without Stop" ")"); do { *((volatile int*)__null) = 2485; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2486 | 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); |
2487 | CleanupConnection(); |
2488 | return; |
2489 | } |
2490 | |
2491 | { |
2492 | MutexAutoLock lock(mMutex); |
2493 | if (mStopped) { |
2494 | return; |
2495 | } |
2496 | |
2497 | if ((mTransport || mConnection) && reason != NS_BASE_STREAM_CLOSED && |
2498 | !mRequestedClose && !mClientClosed && !mServerClosed && mDataStarted) { |
2499 | mRequestedClose = true; |
2500 | mStopOnClose = reason; |
2501 | mIOThread->Dispatch( |
2502 | new OutboundEnqueuer(this, |
2503 | new OutboundMessage(kMsgTypeFin, VoidCString())), |
2504 | nsIEventTarget::DISPATCH_NORMAL); |
2505 | return; |
2506 | } |
2507 | |
2508 | mStopped = true; |
2509 | } |
2510 | |
2511 | DoStopSession(reason); |
2512 | } |
2513 | |
2514 | // ReleaseSession is called on orderly shutdown |
2515 | void WebSocketChannel::ReleaseSession() { |
2516 | 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) |
2517 | !!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); |
2518 | 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" , 2518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 2518; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
2519 | |
2520 | StopSession(NS_OK); |
2521 | } |
2522 | |
2523 | void WebSocketChannel::IncrementSessionCount() { |
2524 | if (!mIncrementedSessionCount) { |
2525 | nsWSAdmissionManager::IncrementSessionCount(); |
2526 | mIncrementedSessionCount = true; |
2527 | } |
2528 | } |
2529 | |
2530 | void WebSocketChannel::DecrementSessionCount() { |
2531 | // Make sure we decrement session count only once, and only if we incremented |
2532 | // it. This code is thread-safe: sWebSocketAdmissions->DecrementSessionCount |
2533 | // is atomic, and mIncrementedSessionCount/mDecrementedSessionCount are set at |
2534 | // times when they'll never be a race condition for checking/setting them. |
2535 | if (mIncrementedSessionCount && !mDecrementedSessionCount) { |
2536 | nsWSAdmissionManager::DecrementSessionCount(); |
2537 | mDecrementedSessionCount = true; |
2538 | } |
2539 | } |
2540 | |
2541 | namespace { |
2542 | enum ExtensionParseMode { eParseServerSide, eParseClientSide }; |
2543 | } |
2544 | |
2545 | static nsresult ParseWebSocketExtension(const nsACString& aExtension, |
2546 | ExtensionParseMode aMode, |
2547 | bool& aClientNoContextTakeover, |
2548 | bool& aServerNoContextTakeover, |
2549 | int32_t& aClientMaxWindowBits, |
2550 | int32_t& aServerMaxWindowBits) { |
2551 | nsCCharSeparatedTokenizer tokens(aExtension, ';'); |
2552 | |
2553 | if (!tokens.hasMoreTokens() || |
2554 | !tokens.nextToken().EqualsLiteral("permessage-deflate")) { |
2555 | 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) |
2556 | ("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) |
2557 | "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) |
2558 | 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); |
2559 | return NS_ERROR_ILLEGAL_VALUE; |
2560 | } |
2561 | |
2562 | aClientNoContextTakeover = aServerNoContextTakeover = false; |
2563 | aClientMaxWindowBits = aServerMaxWindowBits = -1; |
2564 | |
2565 | while (tokens.hasMoreTokens()) { |
2566 | auto token = tokens.nextToken(); |
2567 | |
2568 | int32_t nameEnd, valueStart; |
2569 | int32_t delimPos = token.FindChar('='); |
2570 | if (delimPos == kNotFound) { |
2571 | nameEnd = token.Length(); |
2572 | valueStart = token.Length(); |
2573 | } else { |
2574 | nameEnd = delimPos; |
2575 | valueStart = delimPos + 1; |
2576 | } |
2577 | |
2578 | auto paramName = Substring(token, 0, nameEnd); |
2579 | auto paramValue = Substring(token, valueStart); |
2580 | |
2581 | if (paramName.EqualsLiteral("client_no_context_takeover")) { |
2582 | if (!paramValue.IsEmpty()) { |
2583 | 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) |
2584 | ("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) |
2585 | "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) |
2586 | 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); |
2587 | return NS_ERROR_ILLEGAL_VALUE; |
2588 | } |
2589 | if (aClientNoContextTakeover) { |
2590 | 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) |
2591 | ("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) |
2592 | "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); |
2593 | return NS_ERROR_ILLEGAL_VALUE; |
2594 | } |
2595 | aClientNoContextTakeover = true; |
2596 | } else if (paramName.EqualsLiteral("server_no_context_takeover")) { |
2597 | if (!paramValue.IsEmpty()) { |
2598 | 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) |
2599 | ("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) |
2600 | "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) |
2601 | 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); |
2602 | return NS_ERROR_ILLEGAL_VALUE; |
2603 | } |
2604 | if (aServerNoContextTakeover) { |
2605 | 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) |
2606 | ("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) |
2607 | "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); |
2608 | return NS_ERROR_ILLEGAL_VALUE; |
2609 | } |
2610 | aServerNoContextTakeover = true; |
2611 | } else if (paramName.EqualsLiteral("client_max_window_bits")) { |
2612 | if (aClientMaxWindowBits != -1) { |
2613 | 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) |
2614 | ("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) |
2615 | "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); |
2616 | return NS_ERROR_ILLEGAL_VALUE; |
2617 | } |
2618 | |
2619 | if (aMode == eParseServerSide && paramValue.IsEmpty()) { |
2620 | // Use -2 to indicate that "client_max_window_bits" has been parsed, |
2621 | // but had no value. |
2622 | aClientMaxWindowBits = -2; |
2623 | } else { |
2624 | nsresult errcode; |
2625 | aClientMaxWindowBits = |
2626 | PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode); |
2627 | if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aClientMaxWindowBits < 8 || |
2628 | aClientMaxWindowBits > 15) { |
2629 | 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) |
2630 | ("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) |
2631 | "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) |
2632 | 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); |
2633 | return NS_ERROR_ILLEGAL_VALUE; |
2634 | } |
2635 | } |
2636 | } else if (paramName.EqualsLiteral("server_max_window_bits")) { |
2637 | if (aServerMaxWindowBits != -1) { |
2638 | 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) |
2639 | ("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) |
2640 | "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); |
2641 | return NS_ERROR_ILLEGAL_VALUE; |
2642 | } |
2643 | |
2644 | nsresult errcode; |
2645 | aServerMaxWindowBits = PromiseFlatCStringTPromiseFlatString<char>(paramValue).ToInteger(&errcode); |
2646 | if (NS_FAILED(errcode)((bool)(__builtin_expect(!!(NS_FAILED_impl(errcode)), 0))) || aServerMaxWindowBits < 8 || |
2647 | aServerMaxWindowBits > 15) { |
2648 | 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) |
2649 | ("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) |
2650 | "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) |
2651 | 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); |
2652 | return NS_ERROR_ILLEGAL_VALUE; |
2653 | } |
2654 | } else { |
2655 | 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) |
2656 | ("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) |
2657 | "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) |
2658 | 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); |
2659 | return NS_ERROR_ILLEGAL_VALUE; |
2660 | } |
2661 | } |
2662 | |
2663 | if (aClientMaxWindowBits == -2) { |
2664 | aClientMaxWindowBits = -1; |
2665 | } |
2666 | |
2667 | return NS_OK; |
2668 | } |
2669 | |
2670 | nsresult WebSocketChannel::HandleExtensions() { |
2671 | 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); |
2672 | |
2673 | nsresult rv; |
2674 | nsAutoCString extensions; |
2675 | |
2676 | 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" , 2676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2676; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2677 | |
2678 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Extensions"_ns, |
Value stored to 'rv' is never read | |
2679 | extensions); |
2680 | extensions.CompressWhitespace(); |
2681 | if (extensions.IsEmpty()) { |
2682 | return NS_OK; |
2683 | } |
2684 | |
2685 | 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) |
2686 | ("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) |
2687 | "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) |
2688 | 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); |
2689 | |
2690 | bool clientNoContextTakeover; |
2691 | bool serverNoContextTakeover; |
2692 | int32_t clientMaxWindowBits; |
2693 | int32_t serverMaxWindowBits; |
2694 | |
2695 | rv = ParseWebSocketExtension(extensions, eParseClientSide, |
2696 | clientNoContextTakeover, serverNoContextTakeover, |
2697 | clientMaxWindowBits, serverMaxWindowBits); |
2698 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2699 | AbortSession(rv); |
2700 | return rv; |
2701 | } |
2702 | |
2703 | if (!mAllowPMCE) { |
2704 | 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: " "Recvd permessage-deflate which wasn't offered\n"); } } while (0) |
2705 | ("WebSocketChannel::HandleExtensions: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__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: " "Recvd permessage-deflate which wasn't offered\n"); } } while (0) |
2706 | "Recvd permessage-deflate which wasn't offered\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__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: " "Recvd permessage-deflate which wasn't offered\n"); } } while (0); |
2707 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
2708 | return NS_ERROR_ILLEGAL_VALUE; |
2709 | } |
2710 | |
2711 | if (clientMaxWindowBits == -1) { |
2712 | clientMaxWindowBits = 15; |
2713 | } |
2714 | if (serverMaxWindowBits == -1) { |
2715 | serverMaxWindowBits = 15; |
2716 | } |
2717 | |
2718 | MutexAutoLock lock(mCompressorMutex); |
2719 | mPMCECompressor = MakeUnique<PMCECompression>( |
2720 | clientNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits); |
2721 | if (mPMCECompressor->Active()) { |
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: PMCE negotiated, %susing " "context takeover, clientMaxWindowBits=%d, " "serverMaxWindowBits=%d\n" , clientNoContextTakeover ? "NOT " : "", clientMaxWindowBits, serverMaxWindowBits); } } while (0) |
2723 | ("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) |
2724 | "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) |
2725 | "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) |
2726 | 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) |
2727 | 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); |
2728 | |
2729 | mNegotiatedExtensions = "permessage-deflate"; |
2730 | } else { |
2731 | 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) |
2732 | ("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) |
2733 | "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); |
2734 | mPMCECompressor = nullptr; |
2735 | AbortSession(NS_ERROR_UNEXPECTED); |
2736 | return NS_ERROR_UNEXPECTED; |
2737 | } |
2738 | |
2739 | return NS_OK; |
2740 | } |
2741 | |
2742 | void ProcessServerWebSocketExtensions(const nsACString& aExtensions, |
2743 | nsACString& aNegotiatedExtensions) { |
2744 | aNegotiatedExtensions.Truncate(); |
2745 | |
2746 | nsCOMPtr<nsIPrefBranch> prefService; |
2747 | prefService = mozilla::components::Preferences::Service(); |
2748 | if (prefService) { |
2749 | bool boolpref; |
2750 | nsresult rv = prefService->GetBoolPref( |
2751 | "network.websocket.extensions.permessage-deflate", &boolpref); |
2752 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !boolpref) { |
2753 | return; |
2754 | } |
2755 | } |
2756 | |
2757 | for (const auto& ext : |
2758 | nsCCharSeparatedTokenizer(aExtensions, ',').ToRange()) { |
2759 | bool clientNoContextTakeover; |
2760 | bool serverNoContextTakeover; |
2761 | int32_t clientMaxWindowBits; |
2762 | int32_t serverMaxWindowBits; |
2763 | |
2764 | nsresult rv = ParseWebSocketExtension( |
2765 | ext, eParseServerSide, clientNoContextTakeover, serverNoContextTakeover, |
2766 | clientMaxWindowBits, serverMaxWindowBits); |
2767 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2768 | // Ignore extensions that we can't parse |
2769 | continue; |
2770 | } |
2771 | |
2772 | aNegotiatedExtensions.AssignLiteral("permessage-deflate"); |
2773 | if (clientNoContextTakeover) { |
2774 | aNegotiatedExtensions.AppendLiteral(";client_no_context_takeover"); |
2775 | } |
2776 | if (serverNoContextTakeover) { |
2777 | aNegotiatedExtensions.AppendLiteral(";server_no_context_takeover"); |
2778 | } |
2779 | if (clientMaxWindowBits != -1) { |
2780 | aNegotiatedExtensions.AppendLiteral(";client_max_window_bits="); |
2781 | aNegotiatedExtensions.AppendInt(clientMaxWindowBits); |
2782 | } |
2783 | if (serverMaxWindowBits != -1) { |
2784 | aNegotiatedExtensions.AppendLiteral(";server_max_window_bits="); |
2785 | aNegotiatedExtensions.AppendInt(serverMaxWindowBits); |
2786 | } |
2787 | |
2788 | return; |
2789 | } |
2790 | } |
2791 | |
2792 | nsresult CalculateWebSocketHashedSecret(const nsACString& aKey, |
2793 | nsACString& aHash) { |
2794 | nsresult rv; |
2795 | nsCString key = aKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_ns; |
2796 | nsCOMPtr<nsICryptoHash> hasher = |
2797 | do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv); |
2798 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 2798); return rv; } } while (false); |
2799 | rv = hasher->Init(nsICryptoHash::SHA1); |
2800 | 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" , 2800); return rv; } } while (false); |
2801 | rv = hasher->Update((const uint8_t*)key.BeginWriting(), key.Length()); |
2802 | 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" , 2802); return rv; } } while (false); |
2803 | return hasher->Finish(true, aHash); |
2804 | } |
2805 | |
2806 | nsresult WebSocketChannel::SetupRequest() { |
2807 | 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); |
2808 | |
2809 | nsresult rv; |
2810 | |
2811 | if (mLoadGroup) { |
2812 | rv = mHttpChannel->SetLoadGroup(mLoadGroup); |
2813 | 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" , 2813); return rv; } } while (false); |
2814 | } |
2815 | |
2816 | rv = mHttpChannel->SetLoadFlags( |
2817 | nsIRequest::LOAD_BACKGROUND | nsIRequest::INHIBIT_CACHING | |
2818 | nsIRequest::LOAD_BYPASS_CACHE | nsIChannel::LOAD_BYPASS_SERVICE_WORKER); |
2819 | 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" , 2819); return rv; } } while (false); |
2820 | |
2821 | // we never let websockets be blocked by head CSS/JS loads to avoid |
2822 | // potential deadlock where server generation of CSS/JS requires |
2823 | // an XHR signal. |
2824 | nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel)); |
2825 | if (cos) { |
2826 | cos->AddClassFlags(nsIClassOfService::Unblocked); |
2827 | } |
2828 | |
2829 | // draft-ietf-hybi-thewebsocketprotocol-07 illustrates Upgrade: websocket |
2830 | // in lower case, so go with that. It is technically case insensitive. |
2831 | rv = mChannel->HTTPUpgrade("websocket"_ns, this); |
2832 | 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" , 2832); return rv; } } while (false); |
2833 | |
2834 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Version"_ns, |
2835 | nsLiteralCString(SEC_WEBSOCKET_VERSION"13"), |
2836 | false); |
2837 | 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" , 2837); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2837; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2838 | |
2839 | if (!mOrigin.IsEmpty()) { |
2840 | rv = mHttpChannel->SetRequestHeader("Origin"_ns, mOrigin, false); |
2841 | 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" , 2841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2841; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2842 | } |
2843 | |
2844 | if (!mProtocol.IsEmpty()) { |
2845 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Protocol"_ns, mProtocol, |
2846 | true); |
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 | } |
2849 | |
2850 | if (mAllowPMCE) { |
2851 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Extensions"_ns, |
2852 | "permessage-deflate"_ns, false); |
2853 | 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" , 2853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2853; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2854 | } |
2855 | |
2856 | uint8_t* secKey; |
2857 | nsAutoCString secKeyString; |
2858 | |
2859 | rv = mRandomGenerator->GenerateRandomBytes(16, &secKey); |
2860 | 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" , 2860); return rv; } } while (false); |
2861 | rv = Base64Encode(reinterpret_cast<const char*>(secKey), 16, secKeyString); |
2862 | free(secKey); |
2863 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2864 | return rv; |
2865 | } |
2866 | |
2867 | rv = mHttpChannel->SetRequestHeader("Sec-WebSocket-Key"_ns, secKeyString, |
2868 | false); |
2869 | 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" , 2869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2869; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2870 | 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); |
2871 | |
2872 | // prepare the value we expect to see in |
2873 | // the sec-websocket-accept response header |
2874 | rv = CalculateWebSocketHashedSecret(secKeyString, mHashedSecret); |
2875 | 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" , 2875); return rv; } } while (false); |
2876 | 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) |
2877 | 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); |
2878 | |
2879 | mHttpChannelId = mHttpChannel->ChannelId(); |
2880 | |
2881 | return NS_OK; |
2882 | } |
2883 | |
2884 | nsresult WebSocketChannel::DoAdmissionDNS() { |
2885 | nsresult rv; |
2886 | |
2887 | nsCString hostName; |
2888 | rv = mURI->GetHost(hostName); |
2889 | 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" , 2889); return rv; } } while (false); |
2890 | mAddress = hostName; |
2891 | nsCString path; |
2892 | rv = mURI->GetFilePath(path); |
2893 | 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" , 2893); return rv; } } while (false); |
2894 | mPath = path; |
2895 | rv = mURI->GetPort(&mPort); |
2896 | 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" , 2896); return rv; } } while (false); |
2897 | if (mPort == -1) mPort = (mEncrypted ? kDefaultWSSPort : kDefaultWSPort); |
2898 | nsCOMPtr<nsIDNSService> dns; |
2899 | dns = mozilla::components::DNS::Service(&rv); |
2900 | 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" , 2900); return rv; } } while (false); |
2901 | nsCOMPtr<nsIEventTarget> main = GetMainThreadSerialEventTarget(); |
2902 | nsCOMPtr<nsICancelable> cancelable; |
2903 | rv = dns->AsyncResolveNative(hostName, nsIDNSService::RESOLVE_TYPE_DEFAULT, |
2904 | nsIDNSService::RESOLVE_DEFAULT_FLAGS, nullptr, |
2905 | this, main, mLoadInfo->GetOriginAttributes(), |
2906 | getter_AddRefs(cancelable)); |
2907 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2908 | return rv; |
2909 | } |
2910 | |
2911 | MutexAutoLock lock(mMutex); |
2912 | 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" , 2912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ")"); do { *((volatile int*)__null) = 2912; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2913 | mCancelable = std::move(cancelable); |
2914 | return rv; |
2915 | } |
2916 | |
2917 | nsresult WebSocketChannel::ApplyForAdmission() { |
2918 | 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); |
2919 | |
2920 | // Websockets has a policy of 1 session at a time being allowed in the |
2921 | // CONNECTING state per server IP address (not hostname) |
2922 | |
2923 | // Check to see if a proxy is being used before making DNS call |
2924 | nsCOMPtr<nsIProtocolProxyService> pps; |
2925 | pps = mozilla::components::ProtocolProxy::Service(); |
2926 | |
2927 | if (!pps) { |
2928 | // go straight to DNS |
2929 | // expect the callback in ::OnLookupComplete |
2930 | 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) |
2931 | "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); |
2932 | return DoAdmissionDNS(); |
2933 | } |
2934 | |
2935 | nsresult rv; |
2936 | nsCOMPtr<nsICancelable> cancelable; |
2937 | rv = pps->AsyncResolve( |
2938 | mHttpChannel, |
2939 | nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY | |
2940 | nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY | |
2941 | nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL, |
2942 | this, nullptr, getter_AddRefs(cancelable)); |
2943 | |
2944 | MutexAutoLock lock(mMutex); |
2945 | 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" , 2945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable" ")"); do { *((volatile int*)__null) = 2945; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2946 | mCancelable = std::move(cancelable); |
2947 | return rv; |
2948 | } |
2949 | |
2950 | // Called after both OnStartRequest and OnTransportAvailable have |
2951 | // executed. This essentially ends the handshake and starts the websockets |
2952 | // protocol state machine. |
2953 | nsresult WebSocketChannel::CallStartWebsocketData() { |
2954 | 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); |
2955 | 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" , 2955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 2955; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
2956 | |
2957 | if (mOpenTimer) { |
2958 | mOpenTimer->Cancel(); |
2959 | mOpenTimer = nullptr; |
2960 | } |
2961 | |
2962 | nsCOMPtr<nsIEventTarget> target = GetTargetThread(); |
2963 | if (target && !target->IsOnCurrentThread()) { |
2964 | return target->Dispatch( |
2965 | NewRunnableMethod("net::WebSocketChannel::StartWebsocketData", this, |
2966 | &WebSocketChannel::StartWebsocketData), |
2967 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2968 | } |
2969 | |
2970 | return StartWebsocketData(); |
2971 | } |
2972 | |
2973 | nsresult WebSocketChannel::StartWebsocketData() { |
2974 | { |
2975 | MutexAutoLock lock(mMutex); |
2976 | 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); |
2977 | 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" , 2977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDataStarted" ") (" "StartWebsocketData twice" ")"); do { *((volatile int* )__null) = 2977; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
2978 | |
2979 | if (mStopped) { |
2980 | 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) |
2981 | ("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) |
2982 | "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); |
2983 | return NS_ERROR_NOT_AVAILABLE; |
2984 | } |
2985 | } |
2986 | |
2987 | RefPtr<WebSocketChannel> self = this; |
2988 | mIOThread->Dispatch(NS_NewRunnableFunction( |
2989 | "WebSocketChannel::StartWebsocketData", [self{std::move(self)}] { |
2990 | 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); |
2991 | |
2992 | NS_DispatchToMainThread( |
2993 | NewRunnableMethod("net::WebSocketChannel::NotifyOnStart", self, |
2994 | &WebSocketChannel::NotifyOnStart), |
2995 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
2996 | |
2997 | nsresult rv = self->mConnection ? self->mConnection->StartReading() |
2998 | : self->mSocketIn->AsyncWait( |
2999 | self, 0, 0, self->mIOThread); |
3000 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3001 | self->AbortSession(rv); |
3002 | } |
3003 | |
3004 | if (self->mPingInterval) { |
3005 | rv = self->StartPinging(); |
3006 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3007 | 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) |
3008 | "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) |
3009 | "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) |
3010 | 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); |
3011 | self->AbortSession(rv); |
3012 | } |
3013 | } |
3014 | })); |
3015 | |
3016 | return NS_OK; |
3017 | } |
3018 | |
3019 | void WebSocketChannel::NotifyOnStart() { |
3020 | 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) |
3021 | 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); |
3022 | mDataStarted = true; |
3023 | if (mListenerMT) { |
3024 | nsresult rv = mListenerMT->mListener->OnStart(mListenerMT->mContext); |
3025 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3026 | 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) |
3027 | ("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) |
3028 | "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) |
3029 | 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); |
3030 | } |
3031 | } |
3032 | } |
3033 | |
3034 | nsresult WebSocketChannel::StartPinging() { |
3035 | 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); |
3036 | 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" , 3036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3036; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3037 | 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" , 3037); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval" ")"); do { *((volatile int*)__null) = 3037; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3038 | 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" , 3038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPingTimer" ")"); do { *((volatile int*)__null) = 3038; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3039 | |
3040 | nsresult rv; |
3041 | rv = NS_NewTimerWithCallback(getter_AddRefs(mPingTimer), this, mPingInterval, |
3042 | nsITimer::TYPE_ONE_SHOT); |
3043 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3044 | 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) |
3045 | (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); |
3046 | } else { |
3047 | 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" , 3047); |
3048 | } |
3049 | |
3050 | return NS_OK; |
3051 | } |
3052 | |
3053 | void WebSocketChannel::ReportConnectionTelemetry(nsresult aStatusCode) { |
3054 | // 3 bits are used. high bit is for wss, middle bit for failed, |
3055 | // and low bit for proxy.. |
3056 | // 0 - 7 : ws-ok-plain, ws-ok-proxy, ws-failed-plain, ws-failed-proxy, |
3057 | // wss-ok-plain, wss-ok-proxy, wss-failed-plain, wss-failed-proxy |
3058 | |
3059 | bool didProxy = false; |
3060 | |
3061 | nsCOMPtr<nsIProxyInfo> pi; |
3062 | nsCOMPtr<nsIProxiedChannel> pc = do_QueryInterface(mChannel); |
3063 | if (pc) pc->GetProxyInfo(getter_AddRefs(pi)); |
3064 | if (pi) { |
3065 | nsAutoCString proxyType; |
3066 | pi->GetType(proxyType); |
3067 | if (!proxyType.IsEmpty() && !proxyType.EqualsLiteral("direct")) { |
3068 | didProxy = true; |
3069 | } |
3070 | } |
3071 | |
3072 | uint8_t value = |
3073 | (mEncrypted ? (1 << 2) : 0) | |
3074 | (!(mGotUpgradeOK && NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1) ))) ? (1 << 1) : 0) | |
3075 | (didProxy ? (1 << 0) : 0); |
3076 | |
3077 | 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); |
3078 | Telemetry::Accumulate(Telemetry::WEBSOCKETS_HANDSHAKE_TYPE, value); |
3079 | } |
3080 | |
3081 | // nsIDNSListener |
3082 | |
3083 | NS_IMETHODIMPnsresult |
3084 | WebSocketChannel::OnLookupComplete(nsICancelable* aRequest, |
3085 | nsIDNSRecord* aRecord, nsresult aStatus) { |
3086 | 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) |
3087 | 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); |
3088 | |
3089 | 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" , 3089); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3089; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3090 | |
3091 | { |
3092 | MutexAutoLock lock(mMutex); |
3093 | mCancelable = nullptr; |
3094 | } |
3095 | |
3096 | if (mStopped) { |
3097 | 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); |
3098 | return NS_OK; |
3099 | } |
3100 | |
3101 | // These failures are not fatal - we just use the hostname as the key |
3102 | if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) { |
3103 | 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); |
3104 | |
3105 | // set host in case we got here without calling DoAdmissionDNS() |
3106 | mURI->GetHost(mAddress); |
3107 | } else { |
3108 | nsCOMPtr<nsIDNSAddrRecord> record = do_QueryInterface(aRecord); |
3109 | 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" , 3109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "record" ")" ); do { *((volatile int*)__null) = 3109; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3110 | nsresult rv = record->GetNextAddrAsString(mAddress); |
3111 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3112 | 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); |
3113 | } |
3114 | } |
3115 | |
3116 | 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); |
3117 | nsWSAdmissionManager::ConditionallyConnect(this); |
3118 | |
3119 | return NS_OK; |
3120 | } |
3121 | |
3122 | // nsIProtocolProxyCallback |
3123 | NS_IMETHODIMPnsresult |
3124 | WebSocketChannel::OnProxyAvailable(nsICancelable* aRequest, |
3125 | nsIChannel* aChannel, nsIProxyInfo* pi, |
3126 | nsresult status) { |
3127 | { |
3128 | MutexAutoLock lock(mMutex); |
3129 | 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" , 3129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCancelable || (aRequest == mCancelable)" ")"); do { *((volatile int*)__null) = 3129; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3130 | mCancelable = nullptr; |
3131 | } |
3132 | |
3133 | if (mStopped) { |
3134 | 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) |
3135 | 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); |
3136 | return NS_OK; |
3137 | } |
3138 | |
3139 | nsAutoCString type; |
3140 | 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))) && |
3141 | !type.EqualsLiteral("direct")) { |
3142 | 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) |
3143 | 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); |
3144 | // call DNS callback directly without DNS resolver |
3145 | OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); |
3146 | } else { |
3147 | 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) |
3148 | 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); |
3149 | nsresult rv = DoAdmissionDNS(); |
3150 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3151 | 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); |
3152 | // call DNS callback directly without DNS resolver |
3153 | OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE); |
3154 | } |
3155 | } |
3156 | |
3157 | // notify listener of OnProxyAvailable |
3158 | 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) |
3159 | 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); |
3160 | nsresult rv; |
3161 | nsCOMPtr<nsIProtocolProxyCallback> ppc( |
3162 | do_QueryInterface(mListenerMT->mListener, &rv)); |
3163 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3164 | rv = ppc->OnProxyAvailable(aRequest, aChannel, pi, status); |
3165 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3166 | 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) |
3167 | ("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) |
3168 | " 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) |
3169 | 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); |
3170 | } |
3171 | } |
3172 | |
3173 | return NS_OK; |
3174 | } |
3175 | |
3176 | // nsIInterfaceRequestor |
3177 | |
3178 | NS_IMETHODIMPnsresult |
3179 | WebSocketChannel::GetInterface(const nsIID& iid, void** result) { |
3180 | 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); |
3181 | |
3182 | if (iid.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::COMTypeInfo<nsIChannelEventSink, void >::kIID))) { |
3183 | return QueryInterface(iid, result); |
3184 | } |
3185 | |
3186 | if (mCallbacks) return mCallbacks->GetInterface(iid, result); |
3187 | |
3188 | return NS_ERROR_NO_INTERFACE; |
3189 | } |
3190 | |
3191 | // nsIChannelEventSink |
3192 | |
3193 | NS_IMETHODIMPnsresult |
3194 | WebSocketChannel::AsyncOnChannelRedirect( |
3195 | nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t flags, |
3196 | nsIAsyncVerifyRedirectCallback* callback) { |
3197 | 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); |
3198 | |
3199 | 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" , 3199); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3199; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3200 | |
3201 | nsresult rv; |
3202 | |
3203 | nsCOMPtr<nsIURI> newuri; |
3204 | rv = newChannel->GetURI(getter_AddRefs(newuri)); |
3205 | 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" , 3205); return rv; } } while (false); |
3206 | |
3207 | // newuri is expected to be http or https |
3208 | bool newuriIsHttps = newuri->SchemeIs("https"); |
3209 | |
3210 | // allow insecure->secure redirects for HTTP Strict Transport Security (from |
3211 | // ws://FOO to https://FOO (mapped to wss://FOO) |
3212 | if (!(flags & (nsIChannelEventSink::REDIRECT_INTERNAL | |
3213 | nsIChannelEventSink::REDIRECT_STS_UPGRADE))) { |
3214 | nsAutoCString newSpec; |
3215 | rv = newuri->GetSpec(newSpec); |
3216 | 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" , 3216); return rv; } } while (false); |
3217 | |
3218 | 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) |
3219 | 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); |
3220 | return NS_ERROR_FAILURE; |
3221 | } |
3222 | |
3223 | if (mEncrypted && !newuriIsHttps) { |
3224 | nsAutoCString spec; |
3225 | if (NS_SUCCEEDED(newuri->GetSpec(spec))((bool)(__builtin_expect(!!(!NS_FAILED_impl(newuri->GetSpec (spec))), 1)))) { |
3226 | 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) |
3227 | 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); |
3228 | } |
3229 | return NS_ERROR_FAILURE; |
3230 | } |
3231 | |
3232 | nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(newChannel, &rv); |
3233 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3234 | 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); |
3235 | return rv; |
3236 | } |
3237 | |
3238 | nsCOMPtr<nsIHttpChannelInternal> newUpgradeChannel = |
3239 | do_QueryInterface(newChannel, &rv); |
3240 | |
3241 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3242 | 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); |
3243 | return rv; |
3244 | } |
3245 | |
3246 | // The redirect is likely OK |
3247 | |
3248 | newChannel->SetNotificationCallbacks(this); |
3249 | |
3250 | mEncrypted = newuriIsHttps; |
3251 | rv = NS_MutateURI(newuri) |
3252 | .SetScheme(mEncrypted ? "wss"_ns : "ws"_ns) |
3253 | .Finalize(mURI); |
3254 | |
3255 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3256 | 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); |
3257 | return rv; |
3258 | } |
3259 | |
3260 | mHttpChannel = newHttpChannel; |
3261 | mChannel = newUpgradeChannel; |
3262 | rv = SetupRequest(); |
3263 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3264 | 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); |
3265 | return rv; |
3266 | } |
3267 | |
3268 | // Redirected-to URI may need to be delayed by 1-connecting-per-host and |
3269 | // delay-after-fail algorithms. So hold off calling OnRedirectVerifyCallback |
3270 | // until BeginOpen, when we know it's OK to proceed with new channel. |
3271 | mRedirectCallback = callback; |
3272 | |
3273 | // Mark old channel as successfully connected so we'll clear any FailDelay |
3274 | // associated with the old URI. Note: no need to also call OnStopSession: |
3275 | // it's a no-op for successful, already-connected channels. |
3276 | nsWSAdmissionManager::OnConnected(this); |
3277 | |
3278 | // ApplyForAdmission as if we were starting from fresh... |
3279 | mAddress.Truncate(); |
3280 | mOpenedHttpChannel = false; |
3281 | rv = ApplyForAdmission(); |
3282 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3283 | 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); |
3284 | mRedirectCallback = nullptr; |
3285 | return rv; |
3286 | } |
3287 | |
3288 | return NS_OK; |
3289 | } |
3290 | |
3291 | // nsITimerCallback |
3292 | |
3293 | NS_IMETHODIMPnsresult |
3294 | WebSocketChannel::Notify(nsITimer* timer) { |
3295 | 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); |
3296 | |
3297 | if (timer == mCloseTimer) { |
3298 | 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" , 3298); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientClosed" ") (" "Close Timeout without local close" ")"); do { *((volatile int*)__null) = 3298; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3299 | 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" , 3299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3299; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3300 | |
3301 | mCloseTimer = nullptr; |
3302 | if (mStopped || mServerClosed) { /* no longer relevant */ |
3303 | return NS_OK; |
3304 | } |
3305 | |
3306 | 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); |
3307 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3308 | } else if (timer == mOpenTimer) { |
3309 | 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" , 3309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3309; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3310 | |
3311 | mOpenTimer = nullptr; |
3312 | 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); |
3313 | if (mStopped || mServerClosed) { /* no longer relevant */ |
3314 | return NS_OK; |
3315 | } |
3316 | |
3317 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3318 | MOZ_PUSH_IGNORE_THREAD_SAFETYGCC diagnostic push
GCC diagnostic ignored "-Wthread-safety" |
3319 | // mReconnectDelayTimer is only modified on MainThread, we can read it |
3320 | // without a lock, but ONLY if we're on MainThread! And if we're not |
3321 | // on MainThread, it can't be mReconnectDelayTimer |
3322 | } else if (NS_IsMainThread() && timer == mReconnectDelayTimer) { |
3323 | MOZ_POP_THREAD_SAFETYGCC diagnostic pop |
3324 | 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" , 3325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED" ") (" "woke up from delay w/o being delayed?" ")"); do { *(( volatile int*)__null) = 3325; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
3325 | "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" , 3325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnecting == CONNECTING_DELAYED" ") (" "woke up from delay w/o being delayed?" ")"); do { *(( volatile int*)__null) = 3325; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
3326 | |
3327 | { |
3328 | MutexAutoLock lock(mMutex); |
3329 | mReconnectDelayTimer = nullptr; |
3330 | } |
3331 | 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); |
3332 | BeginOpen(false); |
3333 | } else if (timer == mPingTimer) { |
3334 | 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" , 3334); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 3334; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3335 | |
3336 | if (mClientClosed || mServerClosed || mRequestedClose) { |
3337 | // no point in worrying about ping now |
3338 | mPingTimer = nullptr; |
3339 | return NS_OK; |
3340 | } |
3341 | |
3342 | if (!mPingOutstanding) { |
3343 | // Ping interval must be non-null or PING was forced by OnNetworkChanged() |
3344 | 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" , 3344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPingInterval || mPingForced" ")"); do { *((volatile int*)__null) = 3344; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3345 | 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); |
3346 | mPingOutstanding = 1; |
3347 | mPingForced = false; |
3348 | mPingTimer->InitWithCallback(this, mPingResponseTimeout, |
3349 | nsITimer::TYPE_ONE_SHOT); |
3350 | GeneratePing(); |
3351 | } else { |
3352 | 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); |
3353 | mPingTimer = nullptr; |
3354 | AbortSession(NS_ERROR_NET_TIMEOUT_EXTERNAL); |
3355 | } |
3356 | } else if (timer == mLingeringCloseTimer) { |
3357 | 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); |
3358 | CleanupConnection(); |
3359 | } else { |
3360 | 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" , 3360); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0" ") (" "Unknown Timer" ")"); do { *((volatile int*)__null) = 3360; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3361 | } |
3362 | |
3363 | return NS_OK; |
3364 | } |
3365 | |
3366 | // nsINamed |
3367 | |
3368 | NS_IMETHODIMPnsresult |
3369 | WebSocketChannel::GetName(nsACString& aName) { |
3370 | aName.AssignLiteral("WebSocketChannel"); |
3371 | return NS_OK; |
3372 | } |
3373 | |
3374 | // nsIWebSocketChannel |
3375 | |
3376 | NS_IMETHODIMPnsresult |
3377 | WebSocketChannel::GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) { |
3378 | 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); |
3379 | 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" , 3379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3379; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3380 | |
3381 | *aSecurityInfo = nullptr; |
3382 | |
3383 | if (mConnection) { |
3384 | nsresult rv = mConnection->GetSecurityInfo(aSecurityInfo); |
3385 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3386 | return rv; |
3387 | } |
3388 | return NS_OK; |
3389 | } |
3390 | |
3391 | if (mTransport) { |
3392 | nsCOMPtr<nsITLSSocketControl> tlsSocketControl; |
3393 | nsresult rv = |
3394 | mTransport->GetTlsSocketControl(getter_AddRefs(tlsSocketControl)); |
3395 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3396 | return rv; |
3397 | } |
3398 | nsCOMPtr<nsITransportSecurityInfo> securityInfo( |
3399 | do_QueryInterface(tlsSocketControl)); |
3400 | if (securityInfo) { |
3401 | securityInfo.forget(aSecurityInfo); |
3402 | } |
3403 | } |
3404 | return NS_OK; |
3405 | } |
3406 | |
3407 | NS_IMETHODIMPnsresult |
3408 | WebSocketChannel::AsyncOpen(nsIURI* aURI, const nsACString& aOrigin, |
3409 | JS::Handle<JS::Value> aOriginAttributes, |
3410 | uint64_t aInnerWindowID, |
3411 | nsIWebSocketListener* aListener, |
3412 | nsISupports* aContext, JSContext* aCx) { |
3413 | OriginAttributes attrs; |
3414 | if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { |
3415 | return NS_ERROR_INVALID_ARG; |
3416 | } |
3417 | return AsyncOpenNative(aURI, aOrigin, attrs, aInnerWindowID, aListener, |
3418 | aContext); |
3419 | } |
3420 | |
3421 | NS_IMETHODIMPnsresult |
3422 | WebSocketChannel::AsyncOpenNative(nsIURI* aURI, const nsACString& aOrigin, |
3423 | const OriginAttributes& aOriginAttributes, |
3424 | uint64_t aInnerWindowID, |
3425 | nsIWebSocketListener* aListener, |
3426 | nsISupports* aContext) { |
3427 | 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); |
3428 | |
3429 | aOriginAttributes.CreateSuffix(mOriginSuffix); |
3430 | |
3431 | if (!NS_IsMainThread()) { |
3432 | 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" , 3432); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3432 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3433 | 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); |
3434 | return NS_ERROR_UNEXPECTED; |
3435 | } |
3436 | |
3437 | if ((!aURI && !mIsServerSide) || !aListener) { |
3438 | 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); |
3439 | return NS_ERROR_UNEXPECTED; |
3440 | } |
3441 | |
3442 | if (mListenerMT || mWasOpened) return NS_ERROR_ALREADY_OPENED; |
3443 | |
3444 | nsresult rv; |
3445 | |
3446 | // Ensure target thread is set if RetargetDeliveryTo isn't called |
3447 | { |
3448 | auto lock = mTargetThread.Lock(); |
3449 | if (!lock.ref()) { |
3450 | lock.ref() = GetMainThreadSerialEventTarget(); |
3451 | } |
3452 | } |
3453 | |
3454 | mIOThread = mozilla::components::SocketTransport::Service(&rv); |
3455 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3456 | 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" , 3456); |
3457 | return rv; |
3458 | } |
3459 | |
3460 | nsCOMPtr<nsIPrefBranch> prefService; |
3461 | prefService = mozilla::components::Preferences::Service(); |
3462 | |
3463 | if (prefService) { |
3464 | int32_t intpref; |
3465 | bool boolpref; |
3466 | rv = |
3467 | prefService->GetIntPref("network.websocket.max-message-size", &intpref); |
3468 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3469 | mMaxMessageSize = clamped(intpref, 1024, INT32_MAX(2147483647)); |
3470 | } |
3471 | rv = prefService->GetIntPref("network.websocket.timeout.close", &intpref); |
3472 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3473 | mCloseTimeout = clamped(intpref, 1, 1800) * 1000; |
3474 | } |
3475 | rv = prefService->GetIntPref("network.websocket.timeout.open", &intpref); |
3476 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3477 | mOpenTimeout = clamped(intpref, 1, 1800) * 1000; |
3478 | } |
3479 | rv = prefService->GetIntPref("network.websocket.timeout.ping.request", |
3480 | &intpref); |
3481 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingInterval) { |
3482 | mPingInterval = clamped(intpref, 0, 86400) * 1000; |
3483 | } |
3484 | rv = prefService->GetIntPref("network.websocket.timeout.ping.response", |
3485 | &intpref); |
3486 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mClientSetPingTimeout) { |
3487 | mPingResponseTimeout = clamped(intpref, 1, 3600) * 1000; |
3488 | } |
3489 | rv = prefService->GetBoolPref( |
3490 | "network.websocket.extensions.permessage-deflate", &boolpref); |
3491 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3492 | mAllowPMCE = boolpref ? 1 : 0; |
3493 | } |
3494 | rv = prefService->GetIntPref("network.websocket.max-connections", &intpref); |
3495 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3496 | mMaxConcurrentConnections = clamped(intpref, 1, 0xffff); |
3497 | } |
3498 | } |
3499 | |
3500 | int32_t sessionCount = -1; |
3501 | nsWSAdmissionManager::GetSessionCount(sessionCount); |
3502 | if (sessionCount >= 0) { |
3503 | 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) |
3504 | 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); |
3505 | } |
3506 | |
3507 | if (sessionCount >= mMaxConcurrentConnections) { |
3508 | 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) |
3509 | 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); |
3510 | |
3511 | // WebSocket connections are expected to be long lived, so return |
3512 | // an error here instead of queueing |
3513 | return NS_ERROR_SOCKET_CREATE_FAILED; |
3514 | } |
3515 | |
3516 | mInnerWindowID = aInnerWindowID; |
3517 | mOriginalURI = aURI; |
3518 | mURI = mOriginalURI; |
3519 | mOrigin = aOrigin; |
3520 | |
3521 | if (mIsServerSide) { |
3522 | // IncrementSessionCount(); |
3523 | mWasOpened = 1; |
3524 | mListenerMT = new ListenerAndContextContainer(aListener, aContext); |
3525 | rv = mServerTransportProvider->SetListener(this); |
3526 | 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" , 3526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3526; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3527 | mServerTransportProvider = nullptr; |
3528 | |
3529 | return NS_OK; |
3530 | } |
3531 | |
3532 | mURI->GetHostPort(mHost); |
3533 | |
3534 | mRandomGenerator = mozilla::components::RandomGenerator::Service(&rv); |
3535 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3536 | 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" , 3536); |
3537 | return rv; |
3538 | } |
3539 | |
3540 | nsCOMPtr<nsIURI> localURI; |
3541 | nsCOMPtr<nsIChannel> localChannel; |
3542 | |
3543 | rv = NS_MutateURI(mURI) |
3544 | .SetScheme(mEncrypted ? "https"_ns : "http"_ns) |
3545 | .Finalize(localURI); |
3546 | 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" , 3546); return rv; } } while (false); |
3547 | |
3548 | nsCOMPtr<nsIIOService> ioService; |
3549 | ioService = mozilla::components::IO::Service(&rv); |
3550 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3551 | 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" , 3551); |
3552 | return rv; |
3553 | } |
3554 | |
3555 | // Ideally we'd call newChannelFromURIWithLoadInfo here, but that doesn't |
3556 | // allow setting proxy uri/flags |
3557 | rv = ioService->NewChannelFromURIWithProxyFlags( |
3558 | localURI, mURI, |
3559 | nsIProtocolProxyService::RESOLVE_PREFER_SOCKS_PROXY | |
3560 | nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY | |
3561 | nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL, |
3562 | mLoadInfo->LoadingNode(), mLoadInfo->GetLoadingPrincipal(), |
3563 | mLoadInfo->TriggeringPrincipal(), mLoadInfo->GetSecurityFlags(), |
3564 | mLoadInfo->InternalContentPolicyType(), getter_AddRefs(localChannel)); |
3565 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/websocket/WebSocketChannel.cpp" , 3565); return rv; } } while (false); |
3566 | |
3567 | // Please note that we still call SetLoadInfo on the channel because |
3568 | // we want the same instance of the loadInfo to be set on the channel. |
3569 | rv = localChannel->SetLoadInfo(mLoadInfo); |
3570 | 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" , 3570); return rv; } } while (false); |
3571 | |
3572 | // Pass most GetInterface() requests through to our instantiator, but handle |
3573 | // nsIChannelEventSink in this object in order to deal with redirects |
3574 | localChannel->SetNotificationCallbacks(this); |
3575 | |
3576 | class MOZ_STACK_CLASS CleanUpOnFailure { |
3577 | public: |
3578 | explicit CleanUpOnFailure(WebSocketChannel* aWebSocketChannel) |
3579 | : mWebSocketChannel(aWebSocketChannel) {} |
3580 | |
3581 | ~CleanUpOnFailure() { |
3582 | if (!mWebSocketChannel->mWasOpened) { |
3583 | mWebSocketChannel->mChannel = nullptr; |
3584 | mWebSocketChannel->mHttpChannel = nullptr; |
3585 | } |
3586 | } |
3587 | |
3588 | WebSocketChannel* mWebSocketChannel; |
3589 | }; |
3590 | |
3591 | CleanUpOnFailure cuof(this); |
3592 | |
3593 | mChannel = do_QueryInterface(localChannel, &rv); |
3594 | 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" , 3594); return rv; } } while (false); |
3595 | |
3596 | mHttpChannel = do_QueryInterface(localChannel, &rv); |
3597 | 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" , 3597); return rv; } } while (false); |
3598 | |
3599 | rv = SetupRequest(); |
3600 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3601 | |
3602 | mPrivateBrowsing = NS_UsePrivateBrowsing(localChannel); |
3603 | |
3604 | if (mConnectionLogService && !mPrivateBrowsing) { |
3605 | mConnectionLogService->AddHost(mHost, mSerial, |
3606 | BaseWebSocketChannel::mEncrypted); |
3607 | } |
3608 | |
3609 | rv = ApplyForAdmission(); |
3610 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3611 | |
3612 | // Register for prefs change notifications |
3613 | nsCOMPtr<nsIObserverService> observerService = |
3614 | mozilla::services::GetObserverService(); |
3615 | if (!observerService) { |
3616 | 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" , 3616); |
3617 | return NS_ERROR_FAILURE; |
3618 | } |
3619 | |
3620 | rv = observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC"network:link-status-changed", false); |
3621 | 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" , 3621)) { |
3622 | return rv; |
3623 | } |
3624 | |
3625 | // Only set these if the open was successful: |
3626 | // |
3627 | mWasOpened = 1; |
3628 | mListenerMT = new ListenerAndContextContainer(aListener, aContext); |
3629 | IncrementSessionCount(); |
3630 | |
3631 | return rv; |
3632 | } |
3633 | |
3634 | NS_IMETHODIMPnsresult |
3635 | WebSocketChannel::Close(uint16_t code, const nsACString& reason) { |
3636 | 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); |
3637 | 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" , 3637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3637; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3638 | |
3639 | { |
3640 | MutexAutoLock lock(mMutex); |
3641 | |
3642 | if (mRequestedClose) { |
3643 | return NS_OK; |
3644 | } |
3645 | |
3646 | if (mStopped) { |
3647 | return NS_ERROR_NOT_AVAILABLE; |
3648 | } |
3649 | |
3650 | // The API requires the UTF-8 string to be 123 or less bytes |
3651 | if (reason.Length() > 123) return NS_ERROR_ILLEGAL_VALUE; |
3652 | |
3653 | mRequestedClose = true; |
3654 | mScriptCloseReason = reason; |
3655 | mScriptCloseCode = code; |
3656 | |
3657 | if (mDataStarted) { |
3658 | return mIOThread->Dispatch( |
3659 | new OutboundEnqueuer(this, |
3660 | new OutboundMessage(kMsgTypeFin, VoidCString())), |
3661 | nsIEventTarget::DISPATCH_NORMAL); |
3662 | } |
3663 | |
3664 | mStopped = true; |
3665 | } |
3666 | |
3667 | nsresult rv; |
3668 | if (code == CLOSE_GOING_AWAY) { |
3669 | // Not an error: for example, tab has closed or navigated away |
3670 | 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); |
3671 | rv = NS_OK; |
3672 | } else { |
3673 | 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); |
3674 | rv = NS_ERROR_NOT_CONNECTED; |
3675 | } |
3676 | |
3677 | DoStopSession(rv); |
3678 | return rv; |
3679 | } |
3680 | |
3681 | NS_IMETHODIMPnsresult |
3682 | WebSocketChannel::SendMsg(const nsACString& aMsg) { |
3683 | 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); |
3684 | |
3685 | return SendMsgCommon(aMsg, false, aMsg.Length()); |
3686 | } |
3687 | |
3688 | NS_IMETHODIMPnsresult |
3689 | WebSocketChannel::SendBinaryMsg(const nsACString& aMsg) { |
3690 | 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); |
3691 | return SendMsgCommon(aMsg, true, aMsg.Length()); |
3692 | } |
3693 | |
3694 | NS_IMETHODIMPnsresult |
3695 | WebSocketChannel::SendBinaryStream(nsIInputStream* aStream, uint32_t aLength) { |
3696 | 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); |
3697 | |
3698 | return SendMsgCommon(VoidCString(), true, aLength, aStream); |
3699 | } |
3700 | |
3701 | nsresult WebSocketChannel::SendMsgCommon(const nsACString& aMsg, bool aIsBinary, |
3702 | uint32_t aLength, |
3703 | nsIInputStream* aStream) { |
3704 | 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" , 3704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnTargetThread()" ") (" "not target thread" ")"); do { *((volatile int*)__null ) = 3704; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3705 | |
3706 | if (!mDataStarted) { |
3707 | 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); |
3708 | return NS_ERROR_UNEXPECTED; |
3709 | } |
3710 | |
3711 | if (mRequestedClose) { |
3712 | 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); |
3713 | return NS_ERROR_UNEXPECTED; |
3714 | } |
3715 | |
3716 | if (mStopped) { |
3717 | 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); |
3718 | return NS_ERROR_NOT_CONNECTED; |
3719 | } |
3720 | |
3721 | 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" , 3721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMaxMessageSize >= 0" ") (" "max message size negative" ")"); do { *((volatile int *)__null) = 3721; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3722 | if (aLength > static_cast<uint32_t>(mMaxMessageSize)) { |
3723 | 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); |
3724 | return NS_ERROR_FILE_TOO_BIG; |
3725 | } |
3726 | |
3727 | if (mConnectionLogService && !mPrivateBrowsing) { |
3728 | mConnectionLogService->NewMsgSent(mHost, mSerial, aLength); |
3729 | 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); |
3730 | } |
3731 | |
3732 | return mIOThread->Dispatch( |
3733 | aStream |
3734 | ? new OutboundEnqueuer(this, new OutboundMessage(aStream, aLength)) |
3735 | : new OutboundEnqueuer( |
3736 | this, |
3737 | new OutboundMessage( |
3738 | aIsBinary ? kMsgTypeBinaryString : kMsgTypeString, aMsg)), |
3739 | nsIEventTarget::DISPATCH_NORMAL); |
3740 | } |
3741 | |
3742 | // nsIHttpUpgradeListener |
3743 | |
3744 | NS_IMETHODIMPnsresult |
3745 | WebSocketChannel::OnTransportAvailable(nsISocketTransport* aTransport, |
3746 | nsIAsyncInputStream* aSocketIn, |
3747 | nsIAsyncOutputStream* aSocketOut) { |
3748 | if (!NS_IsMainThread()) { |
3749 | return NS_DispatchToMainThread( |
3750 | new CallOnTransportAvailable(this, aTransport, aSocketIn, aSocketOut)); |
3751 | } |
3752 | |
3753 | 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) |
3754 | 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); |
3755 | |
3756 | if (mStopped) { |
3757 | 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); |
3758 | return NS_OK; |
3759 | } |
3760 | |
3761 | 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" , 3761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3761; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3762 | 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" , 3762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OTA duplicated" ")"); do { *((volatile int*)__null) = 3762; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3763 | 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" , 3763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSocketIn" ") (" "OTA with invalid socketIn" ")"); do { *((volatile int*)__null ) = 3763; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3764 | |
3765 | mTransport = aTransport; |
3766 | mSocketIn = aSocketIn; |
3767 | mSocketOut = aSocketOut; |
3768 | |
3769 | nsresult rv; |
3770 | rv = mTransport->SetEventSink(nullptr, nullptr); |
3771 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3772 | rv = mTransport->SetSecurityCallbacks(this); |
3773 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
3774 | |
3775 | return OnTransportAvailableInternal(); |
3776 | } |
3777 | |
3778 | NS_IMETHODIMPnsresult |
3779 | WebSocketChannel::OnWebSocketConnectionAvailable( |
3780 | WebSocketConnectionBase* aConnection) { |
3781 | if (!NS_IsMainThread()) { |
3782 | RefPtr<WebSocketChannel> self = this; |
3783 | RefPtr<WebSocketConnectionBase> connection = aConnection; |
3784 | return NS_DispatchToMainThread(NS_NewRunnableFunction( |
3785 | "WebSocketChannel::OnWebSocketConnectionAvailable", |
3786 | [self, connection]() { |
3787 | self->OnWebSocketConnectionAvailable(connection); |
3788 | })); |
3789 | } |
3790 | |
3791 | 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) |
3792 | ("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) |
3793 | "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) |
3794 | 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); |
3795 | |
3796 | 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" , 3796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3796; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3797 | 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" , 3798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3798; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
3798 | "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" , 3798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3798; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
3799 | 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" , 3799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aConnection" ")"); do { *((volatile int*)__null) = 3799; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3800 | |
3801 | if (mStopped) { |
3802 | 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); |
3803 | aConnection->Close(); |
3804 | return NS_OK; |
3805 | } |
3806 | |
3807 | nsresult rv = aConnection->Init(this); |
3808 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3809 | return rv; |
3810 | } |
3811 | |
3812 | mConnection = aConnection; |
3813 | // Note: mIOThread will be IPDL background thread. |
3814 | mConnection->GetIoTarget(getter_AddRefs(mIOThread)); |
3815 | return OnTransportAvailableInternal(); |
3816 | } |
3817 | |
3818 | nsresult WebSocketChannel::OnTransportAvailableInternal() { |
3819 | 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" , 3819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3820 | 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" , 3821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3821; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
3821 | "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" , 3821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OnWebSocketConnectionAvailable duplicated" ")"); do { *((volatile int*)__null) = 3821; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
3822 | 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" , 3822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSocketIn || mConnection" ")"); do { *((volatile int*)__null) = 3822; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3823 | |
3824 | mRecvdHttpUpgradeTransport = 1; |
3825 | if (mGotUpgradeOK) { |
3826 | // We're now done CONNECTING, which means we can now open another, |
3827 | // perhaps parallel, connection to the same host if one |
3828 | // is pending |
3829 | nsWSAdmissionManager::OnConnected(this); |
3830 | |
3831 | return CallStartWebsocketData(); |
3832 | } |
3833 | |
3834 | if (mIsServerSide) { |
3835 | if (!mNegotiatedExtensions.IsEmpty()) { |
3836 | bool clientNoContextTakeover; |
3837 | bool serverNoContextTakeover; |
3838 | int32_t clientMaxWindowBits; |
3839 | int32_t serverMaxWindowBits; |
3840 | |
3841 | nsresult rv = ParseWebSocketExtension( |
3842 | mNegotiatedExtensions, eParseServerSide, clientNoContextTakeover, |
3843 | serverNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits); |
3844 | 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" , 3844); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ") (" "illegal value provided by server" ")"); do { *((volatile int*)__null) = 3844; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3845 | |
3846 | if (clientMaxWindowBits == -1) { |
3847 | clientMaxWindowBits = 15; |
3848 | } |
3849 | if (serverMaxWindowBits == -1) { |
3850 | serverMaxWindowBits = 15; |
3851 | } |
3852 | |
3853 | MutexAutoLock lock(mCompressorMutex); |
3854 | mPMCECompressor = MakeUnique<PMCECompression>( |
3855 | serverNoContextTakeover, serverMaxWindowBits, clientMaxWindowBits); |
3856 | if (mPMCECompressor->Active()) { |
3857 | 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) |
3858 | ("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) |
3859 | "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) |
3860 | "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) |
3861 | 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) |
3862 | 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); |
3863 | |
3864 | mNegotiatedExtensions = "permessage-deflate"; |
3865 | } else { |
3866 | 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) |
3867 | ("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) |
3868 | "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); |
3869 | mPMCECompressor = nullptr; |
3870 | AbortSession(NS_ERROR_UNEXPECTED); |
3871 | return NS_ERROR_UNEXPECTED; |
3872 | } |
3873 | } |
3874 | |
3875 | return CallStartWebsocketData(); |
3876 | } |
3877 | |
3878 | return NS_OK; |
3879 | } |
3880 | |
3881 | NS_IMETHODIMPnsresult |
3882 | WebSocketChannel::OnUpgradeFailed(nsresult aErrorCode) { |
3883 | // When socket process is enabled, this could be called on background thread. |
3884 | |
3885 | 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) |
3886 | 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); |
3887 | |
3888 | if (mStopped) { |
3889 | 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); |
3890 | return NS_OK; |
3891 | } |
3892 | |
3893 | 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" , 3893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRecvdHttpUpgradeTransport" ") (" "OTA already called" ")"); do { *((volatile int*)__null ) = 3893; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
3894 | |
3895 | AbortSession(aErrorCode); |
3896 | return NS_OK; |
3897 | } |
3898 | |
3899 | // nsIRequestObserver (from nsIStreamListener) |
3900 | |
3901 | NS_IMETHODIMPnsresult |
3902 | WebSocketChannel::OnStartRequest(nsIRequest* aRequest) { |
3903 | 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) |
3904 | 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); |
3905 | 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" , 3905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 3905; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3906 | 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" , 3906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mGotUpgradeOK" ") (" "OTA duplicated" ")"); do { *((volatile int*)__null) = 3906; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3907 | |
3908 | if (mStopped) { |
3909 | 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); |
3910 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
3911 | return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3912 | } |
3913 | |
3914 | nsresult rv; |
3915 | uint32_t status; |
3916 | char *val, *token; |
3917 | |
3918 | rv = mHttpChannel->GetResponseStatus(&status); |
3919 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3920 | nsresult httpStatus; |
3921 | rv = NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3922 | |
3923 | // If we failed to connect due to unsuccessful TLS handshake, we must |
3924 | // propagate a specific error to mozilla::dom::WebSocketImpl so it can set |
3925 | // status code to 1015. Otherwise return |
3926 | // NS_ERROR_WEBSOCKET_CONNECTION_REFUSED. |
3927 | if (NS_SUCCEEDED(mHttpChannel->GetStatus(&httpStatus))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mHttpChannel-> GetStatus(&httpStatus))), 1)))) { |
3928 | uint32_t errorClass; |
3929 | nsCOMPtr<nsINSSErrorsService> errSvc; |
3930 | errSvc = mozilla::components::NSSErrors::Service(); |
3931 | // If GetErrorClass succeeds httpStatus is TLS related failure. |
3932 | if (errSvc && |
3933 | NS_SUCCEEDED(errSvc->GetErrorClass(httpStatus, &errorClass))((bool)(__builtin_expect(!!(!NS_FAILED_impl(errSvc->GetErrorClass (httpStatus, &errorClass))), 1)))) { |
3934 | rv = NS_ERROR_NET_INADEQUATE_SECURITY; |
3935 | } |
3936 | } |
3937 | |
3938 | 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); |
3939 | AbortSession(rv); |
3940 | return rv; |
3941 | } |
3942 | |
3943 | 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); |
3944 | nsCOMPtr<nsIHttpChannelInternal> internalChannel = |
3945 | do_QueryInterface(mHttpChannel); |
3946 | uint32_t versionMajor, versionMinor; |
3947 | rv = internalChannel->GetResponseVersion(&versionMajor, &versionMinor); |
3948 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || |
3949 | !((versionMajor == 1 && versionMinor != 0) || versionMajor == 2) || |
3950 | (versionMajor == 1 && status != 101) || |
3951 | (versionMajor == 2 && status != 200)) { |
3952 | AbortSession(NS_ERROR_WEBSOCKET_CONNECTION_REFUSED); |
3953 | return NS_ERROR_WEBSOCKET_CONNECTION_REFUSED; |
3954 | } |
3955 | |
3956 | if (versionMajor == 1) { |
3957 | // These are only present on http/1.x websocket upgrades |
3958 | nsAutoCString respUpgrade; |
3959 | rv = mHttpChannel->GetResponseHeader("Upgrade"_ns, respUpgrade); |
3960 | |
3961 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3962 | rv = NS_ERROR_ILLEGAL_VALUE; |
3963 | if (!respUpgrade.IsEmpty()) { |
3964 | val = respUpgrade.BeginWriting(); |
3965 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
3966 | if (nsCRT::strcasecmp(token, "Websocket") == 0) { |
3967 | rv = NS_OK; |
3968 | break; |
3969 | } |
3970 | } |
3971 | } |
3972 | } |
3973 | |
3974 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3975 | 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) |
3976 | ("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) |
3977 | "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); |
3978 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
3979 | return rv; |
3980 | } |
3981 | |
3982 | nsAutoCString respConnection; |
3983 | rv = mHttpChannel->GetResponseHeader("Connection"_ns, respConnection); |
3984 | |
3985 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
3986 | rv = NS_ERROR_ILLEGAL_VALUE; |
3987 | if (!respConnection.IsEmpty()) { |
3988 | val = respConnection.BeginWriting(); |
3989 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
3990 | if (nsCRT::strcasecmp(token, "Upgrade") == 0) { |
3991 | rv = NS_OK; |
3992 | break; |
3993 | } |
3994 | } |
3995 | } |
3996 | } |
3997 | |
3998 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
3999 | 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) |
4000 | ("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) |
4001 | "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); |
4002 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
4003 | return rv; |
4004 | } |
4005 | |
4006 | nsAutoCString respAccept; |
4007 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Accept"_ns, respAccept); |
4008 | |
4009 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty() || |
4010 | !respAccept.Equals(mHashedSecret)) { |
4011 | 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) |
4012 | ("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) |
4013 | "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); |
4014 | 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) |
4015 | 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); |
4016 | #ifdef FUZZING |
4017 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || respAccept.IsEmpty()) { |
4018 | #endif |
4019 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
4020 | return NS_ERROR_ILLEGAL_VALUE; |
4021 | #ifdef FUZZING |
4022 | } |
4023 | #endif |
4024 | } |
4025 | } |
4026 | |
4027 | // If we sent a sub protocol header, verify the response matches. |
4028 | // If response contains protocol that was not in request, fail. |
4029 | // If response contained no protocol header, set to "" so the protocol |
4030 | // attribute of the WebSocket JS object reflects that |
4031 | if (!mProtocol.IsEmpty()) { |
4032 | nsAutoCString respProtocol; |
4033 | rv = mHttpChannel->GetResponseHeader("Sec-WebSocket-Protocol"_ns, |
4034 | respProtocol); |
4035 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
4036 | rv = NS_ERROR_ILLEGAL_VALUE; |
4037 | val = mProtocol.BeginWriting(); |
4038 | while ((token = nsCRT::strtok(val, ", \t", &val))) { |
4039 | if (strcmp(token, respProtocol.get()) == 0) { |
4040 | rv = NS_OK; |
4041 | break; |
4042 | } |
4043 | } |
4044 | |
4045 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
4046 | 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) |
4047 | 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); |
4048 | mProtocol = respProtocol; |
4049 | } else { |
4050 | 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) |
4051 | ("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) |
4052 | "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) |
4053 | 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); |
4054 | mProtocol.Truncate(); |
4055 | AbortSession(NS_ERROR_ILLEGAL_VALUE); |
4056 | return NS_ERROR_ILLEGAL_VALUE; |
4057 | } |
4058 | } else { |
4059 | 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) |
4060 | ("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) |
4061 | "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) |
4062 | 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); |
4063 | mProtocol.Truncate(); |
4064 | } |
4065 | } |
4066 | |
4067 | rv = HandleExtensions(); |
4068 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
4069 | |
4070 | // Update mEffectiveURL for off main thread URI access. |
4071 | nsCOMPtr<nsIURI> uri = mURI ? mURI : mOriginalURI; |
4072 | nsAutoCString spec; |
4073 | rv = uri->GetSpec(spec); |
4074 | 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" , 4074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 4074; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4075 | CopyUTF8toUTF16(spec, mEffectiveURL); |
4076 | |
4077 | mGotUpgradeOK = 1; |
4078 | if (mRecvdHttpUpgradeTransport) { |
4079 | // We're now done CONNECTING, which means we can now open another, |
4080 | // perhaps parallel, connection to the same host if one |
4081 | // is pending |
4082 | nsWSAdmissionManager::OnConnected(this); |
4083 | |
4084 | return CallStartWebsocketData(); |
4085 | } |
4086 | |
4087 | return NS_OK; |
4088 | } |
4089 | |
4090 | NS_IMETHODIMPnsresult |
4091 | WebSocketChannel::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { |
4092 | 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) |
4093 | 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); |
4094 | 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" , 4094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "not main thread" ")"); do { *((volatile int*)__null) = 4094; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4095 | |
4096 | // OnTransportAvailable won't be called if the request is stopped with |
4097 | // an error. Abort the session now instead of waiting for timeout. |
4098 | if (NS_FAILED(aStatusCode)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatusCode)), 0)) ) && !mRecvdHttpUpgradeTransport) { |
4099 | AbortSession(aStatusCode); |
4100 | } |
4101 | |
4102 | ReportConnectionTelemetry(aStatusCode); |
4103 | |
4104 | // This is the end of the HTTP upgrade transaction, the |
4105 | // upgraded streams live on |
4106 | |
4107 | mChannel = nullptr; |
4108 | mHttpChannel = nullptr; |
4109 | mLoadGroup = nullptr; |
4110 | mCallbacks = nullptr; |
4111 | |
4112 | return NS_OK; |
4113 | } |
4114 | |
4115 | // nsIInputStreamCallback |
4116 | |
4117 | NS_IMETHODIMPnsresult |
4118 | WebSocketChannel::OnInputStreamReady(nsIAsyncInputStream* aStream) { |
4119 | 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); |
4120 | 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" , 4120); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4120; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4121 | |
4122 | if (!mSocketIn) { // did we we clean up the socket after scheduling |
4123 | // InputReady? |
4124 | return NS_OK; |
4125 | } |
4126 | |
4127 | // this is after the http upgrade - so we are speaking websockets |
4128 | char buffer[2048]; |
4129 | uint32_t count; |
4130 | nsresult rv; |
4131 | |
4132 | do { |
4133 | rv = mSocketIn->Read((char*)buffer, sizeof(buffer), &count); |
4134 | 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) |
4135 | 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); |
4136 | |
4137 | if (rv == NS_BASE_STREAM_WOULD_BLOCK) { |
4138 | mSocketIn->AsyncWait(this, 0, 0, mIOThread); |
4139 | return NS_OK; |
4140 | } |
4141 | |
4142 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4143 | AbortSession(rv); |
4144 | return rv; |
4145 | } |
4146 | |
4147 | if (count == 0) { |
4148 | AbortSession(NS_BASE_STREAM_CLOSED); |
4149 | return NS_OK; |
4150 | } |
4151 | |
4152 | if (mStopped) { |
4153 | continue; |
4154 | } |
4155 | |
4156 | rv = ProcessInput((uint8_t*)buffer, count); |
4157 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4158 | AbortSession(rv); |
4159 | return rv; |
4160 | } |
4161 | } while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mSocketIn); |
4162 | |
4163 | return NS_OK; |
4164 | } |
4165 | |
4166 | // nsIOutputStreamCallback |
4167 | |
4168 | NS_IMETHODIMPnsresult |
4169 | WebSocketChannel::OnOutputStreamReady(nsIAsyncOutputStream* aStream) { |
4170 | 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); |
4171 | 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" , 4171); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4171; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4172 | nsresult rv; |
4173 | |
4174 | if (!mCurrentOut) PrimeNewOutgoingMessage(); |
4175 | |
4176 | while (mCurrentOut && mSocketOut) { |
4177 | const char* sndBuf; |
4178 | uint32_t toSend; |
4179 | uint32_t amtSent; |
4180 | |
4181 | if (mHdrOut) { |
4182 | sndBuf = (const char*)mHdrOut; |
4183 | toSend = mHdrOutToSend; |
4184 | 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) |
4185 | ("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) |
4186 | "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) |
4187 | 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); |
4188 | } else { |
4189 | sndBuf = (char*)mCurrentOut->BeginReading() + mCurrentOutSent; |
4190 | toSend = mCurrentOut->Length() - mCurrentOutSent; |
4191 | if (toSend > 0) { |
4192 | 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) |
4193 | ("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) |
4194 | "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) |
4195 | 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); |
4196 | } |
4197 | } |
4198 | |
4199 | if (toSend == 0) { |
4200 | amtSent = 0; |
4201 | } else { |
4202 | rv = mSocketOut->Write(sndBuf, toSend, &amtSent); |
4203 | 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) |
4204 | "\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net ::webSocketLog; if ((__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) |
4205 | 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); |
4206 | |
4207 | if (rv == NS_BASE_STREAM_WOULD_BLOCK) { |
4208 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4209 | return NS_OK; |
4210 | } |
4211 | |
4212 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4213 | AbortSession(rv); |
4214 | return NS_OK; |
4215 | } |
4216 | } |
4217 | |
4218 | if (mHdrOut) { |
4219 | if (amtSent == toSend) { |
4220 | mHdrOut = nullptr; |
4221 | mHdrOutToSend = 0; |
4222 | } else { |
4223 | mHdrOut += amtSent; |
4224 | mHdrOutToSend -= amtSent; |
4225 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4226 | } |
4227 | } else { |
4228 | if (amtSent == toSend) { |
4229 | if (!mStopped) { |
4230 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
4231 | target->Dispatch( |
4232 | new CallAcknowledge(this, mCurrentOut->OrigLength()), |
4233 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
4234 | } else { |
4235 | return NS_ERROR_UNEXPECTED; |
4236 | } |
4237 | } |
4238 | DeleteCurrentOutGoingMessage(); |
4239 | PrimeNewOutgoingMessage(); |
4240 | } else { |
4241 | mCurrentOutSent += amtSent; |
4242 | mSocketOut->AsyncWait(this, 0, 0, mIOThread); |
4243 | } |
4244 | } |
4245 | } |
4246 | |
4247 | if (mReleaseOnTransmit) ReleaseSession(); |
4248 | return NS_OK; |
4249 | } |
4250 | |
4251 | // nsIStreamListener |
4252 | |
4253 | NS_IMETHODIMPnsresult |
4254 | WebSocketChannel::OnDataAvailable(nsIRequest* aRequest, |
4255 | nsIInputStream* aInputStream, |
4256 | uint64_t aOffset, uint32_t aCount) { |
4257 | 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) |
4258 | 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); |
4259 | |
4260 | // This is the HTTP OnDataAvailable Method, which means this is http data in |
4261 | // response to the upgrade request and there should be no http response body |
4262 | // if the upgrade succeeded. This generally should be caught by a non 101 |
4263 | // response code in OnStartRequest().. so we can ignore the data here |
4264 | |
4265 | 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) |
4266 | 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); |
4267 | |
4268 | return NS_OK; |
4269 | } |
4270 | |
4271 | void WebSocketChannel::DoEnqueueOutgoingMessage() { |
4272 | 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); |
4273 | 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" , 4273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIOThread->IsOnCurrentThread()" ") (" "not on right thread" ")"); do { *((volatile int*)__null ) = 4273; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4274 | |
4275 | if (!mCurrentOut) { |
4276 | PrimeNewOutgoingMessage(); |
4277 | } |
4278 | |
4279 | while (mCurrentOut && mConnection) { |
4280 | nsresult rv = NS_OK; |
4281 | if (mCurrentOut->Length() - mCurrentOutSent == 0) { |
4282 | 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) |
4283 | ("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) |
4284 | "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) |
4285 | 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); |
4286 | rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, nullptr, 0); |
4287 | } else { |
4288 | 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) |
4289 | ("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) |
4290 | "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) |
4291 | 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); |
4292 | rv = mConnection->WriteOutputData(mOutHeader, mHdrOutToSend, |
4293 | (uint8_t*)mCurrentOut->BeginReading(), |
4294 | mCurrentOut->Length()); |
4295 | } |
4296 | |
4297 | 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) |
4298 | 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); |
4299 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4300 | AbortSession(rv); |
4301 | return; |
4302 | } |
4303 | |
4304 | if (!mStopped) { |
4305 | // TODO: Currently, we assume that data is completely written to the |
4306 | // socket after sending it to socket process, but it's not true. The data |
4307 | // could be queued in socket process and waiting for the socket to be able |
4308 | // to write. We should implement flow control for this in bug 1726552. |
4309 | if (nsCOMPtr<nsIEventTarget> target = GetTargetThread()) { |
4310 | target->Dispatch(new CallAcknowledge(this, mCurrentOut->OrigLength()), |
4311 | NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL); |
4312 | } else { |
4313 | AbortSession(NS_ERROR_UNEXPECTED); |
4314 | return; |
4315 | } |
4316 | } |
4317 | DeleteCurrentOutGoingMessage(); |
4318 | PrimeNewOutgoingMessage(); |
4319 | } |
4320 | |
4321 | if (mReleaseOnTransmit) { |
4322 | ReleaseSession(); |
4323 | } |
4324 | } |
4325 | |
4326 | void WebSocketChannel::OnError(nsresult aStatus) { AbortSession(aStatus); } |
4327 | |
4328 | void WebSocketChannel::OnTCPClosed() { mTCPClosed = true; } |
4329 | |
4330 | nsresult WebSocketChannel::OnDataReceived(uint8_t* aData, uint32_t aCount) { |
4331 | return ProcessInput(aData, aCount); |
4332 | } |
4333 | |
4334 | } // namespace mozilla::net |
4335 | |
4336 | #undef CLOSE_GOING_AWAY |