WebTransport.h (7188B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 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 #ifndef DOM_WEBTRANSPORT_API_WEBTRANSPORT__H_ 8 #define DOM_WEBTRANSPORT_API_WEBTRANSPORT__H_ 9 10 #include "mozilla/dom/Promise.h" 11 #include "mozilla/dom/WebTransportBinding.h" 12 #include "mozilla/dom/WebTransportChild.h" 13 #include "mozilla/dom/WebTransportReceiveStream.h" 14 #include "mozilla/dom/WebTransportSendStream.h" 15 #include "mozilla/dom/WebTransportStreams.h" 16 #include "mozilla/ipc/DataPipe.h" 17 #include "mozilla/net/WebTransportEventService.h" 18 #include "nsCOMPtr.h" 19 #include "nsISupports.h" 20 #include "nsPIDOMWindow.h" 21 #include "nsTArray.h" 22 #include "nsTHashMap.h" 23 #include "nsWrapperCache.h" 24 25 namespace mozilla::dom { 26 27 class WebTransportError; 28 class WebTransportDatagramDuplexStream; 29 class WebTransportIncomingStreamsAlgorithms; 30 class ReadableStream; 31 class WritableStream; 32 using BidirectionalPair = std::pair<RefPtr<mozilla::ipc::DataPipeReceiver>, 33 RefPtr<mozilla::ipc::DataPipeSender>>; 34 35 struct DatagramEntry { 36 DatagramEntry(nsTArray<uint8_t>&& aData, const mozilla::TimeStamp& aTimeStamp) 37 : mBuffer(std::move(aData)), mTimeStamp(aTimeStamp) {} 38 DatagramEntry(Span<uint8_t>& aData, const mozilla::TimeStamp& aTimeStamp) 39 : mBuffer(aData), mTimeStamp(aTimeStamp) {} 40 41 nsTArray<uint8_t> mBuffer; 42 mozilla::TimeStamp mTimeStamp; 43 }; 44 45 class WebTransport final : public nsISupports, public nsWrapperCache { 46 friend class WebTransportIncomingStreamsAlgorithms; 47 // For mSendStreams/mReceiveStreams 48 friend class WebTransportSendStream; 49 friend class WebTransportReceiveStream; 50 51 public: 52 explicit WebTransport(nsIGlobalObject* aGlobal); 53 54 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 55 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WebTransport) 56 57 enum class WebTransportState { CONNECTING, CONNECTED, CLOSED, FAILED }; 58 59 static void NotifyBFCacheOnMainThread(nsPIDOMWindowInner* aInner, 60 bool aCreated); 61 void NotifyToWindow(bool aCreated) const; 62 63 void Init(const GlobalObject& aGlobal, const nsAString& aUrl, 64 const WebTransportOptions& aOptions, ErrorResult& aError); 65 void ResolveWaitingConnection(WebTransportReliabilityMode aReliability); 66 void RejectWaitingConnection(nsresult aRv); 67 bool ParseURL(const nsAString& aURL) const; 68 // this calls CloseNative(), which doesn't actually run script. See bug 69 // 1810942 70 MOZ_CAN_RUN_SCRIPT_BOUNDARY void Cleanup( 71 WebTransportError* aError, const WebTransportCloseInfo* aCloseInfo, 72 ErrorResult& aRv); 73 74 // From Parent 75 void NewBidirectionalStream( 76 uint64_t aStreamId, 77 const RefPtr<mozilla::ipc::DataPipeReceiver>& aIncoming, 78 const RefPtr<mozilla::ipc::DataPipeSender>& aOutgoing); 79 80 void NewUnidirectionalStream( 81 uint64_t aStreamId, 82 const RefPtr<mozilla::ipc::DataPipeReceiver>& aStream); 83 84 void NewDatagramReceived(nsTArray<uint8_t>&& aData, 85 const mozilla::TimeStamp& aTimeStamp); 86 87 void RemoteClosed(bool aCleanly, const uint32_t& aCode, 88 const nsACString& aReason); 89 90 void OnStreamResetOrStopSending(uint64_t aStreamId, 91 const StreamResetOrStopSendingError& aError); 92 // WebIDL Boilerplate 93 nsIGlobalObject* GetParentObject() const; 94 95 JSObject* WrapObject(JSContext* aCx, 96 JS::Handle<JSObject*> aGivenProto) override; 97 98 // WebIDL Interface 99 static already_AddRefed<WebTransport> Constructor( 100 const GlobalObject& aGlobal, const nsAString& aUrl, 101 const WebTransportOptions& aOptions, ErrorResult& aError); 102 103 already_AddRefed<Promise> GetStats(ErrorResult& aError); 104 105 already_AddRefed<Promise> Ready() { return do_AddRef(mReady); } 106 WebTransportReliabilityMode Reliability(); 107 WebTransportCongestionControl CongestionControl(); 108 already_AddRefed<Promise> Closed() { return do_AddRef(mClosed); } 109 MOZ_CAN_RUN_SCRIPT void Close(const WebTransportCloseInfo& aOptions, 110 ErrorResult& aRv); 111 already_AddRefed<WebTransportDatagramDuplexStream> GetDatagrams( 112 ErrorResult& aRv); 113 already_AddRefed<Promise> CreateBidirectionalStream( 114 const WebTransportSendStreamOptions& aOptions, ErrorResult& aRv); 115 already_AddRefed<Promise> CreateUnidirectionalStream( 116 const WebTransportSendStreamOptions& aOptions, ErrorResult& aRv); 117 MOZ_CAN_RUN_SCRIPT_BOUNDARY already_AddRefed<ReadableStream> 118 IncomingBidirectionalStreams(); 119 MOZ_CAN_RUN_SCRIPT_BOUNDARY already_AddRefed<ReadableStream> 120 IncomingUnidirectionalStreams(); 121 122 void SendSetSendOrder(uint64_t aStreamId, Maybe<int64_t> aSendOrder); 123 124 void Shutdown() {} 125 126 private: 127 ~WebTransport(); 128 129 template <typename Stream> 130 MOZ_CAN_RUN_SCRIPT_BOUNDARY void PropagateError(Stream* aStream, 131 WebTransportError* aError); 132 133 nsCOMPtr<nsIGlobalObject> mGlobal; 134 // We are the owner of WebTransportChild. We must call Shutdown() on it 135 // before we're destroyed. 136 RefPtr<WebTransportChild> mChild; 137 138 // Spec in 5.8 says it can't be GC'd while CONNECTING or CONNECTED. We won't 139 // hold ref which we drop on CLOSED or FAILED because a reference is also held 140 // by IPC. We drop the IPC connection and by proxy the reference when it goes 141 // to FAILED or CLOSED. 142 143 // Spec-defined slots: 144 // ordered sets, but we can't have duplicates, and this spec only appends. 145 // Order is visible due to 146 // https://w3c.github.io/webtransport/#webtransport-procedures step 10: "For 147 // each sendStream in sendStreams, error sendStream with error." 148 nsTHashMap<uint64_t, RefPtr<WebTransportSendStream>> mSendStreams; 149 nsTHashMap<uint64_t, RefPtr<WebTransportReceiveStream>> mReceiveStreams; 150 151 WebTransportState mState; 152 RefPtr<Promise> mReady; 153 uint64_t mInnerWindowID = 0; 154 uint64_t mHttpChannelID = 0; 155 uint64_t mBrowsingContextID = 0; 156 RefPtr<mozilla::net::WebTransportEventService> mService; 157 // XXX may not need to be a RefPtr, since we own it through the Streams 158 RefPtr<WebTransportIncomingStreamsAlgorithms> mIncomingBidirectionalAlgorithm; 159 RefPtr<WebTransportIncomingStreamsAlgorithms> 160 mIncomingUnidirectionalAlgorithm; 161 WebTransportReliabilityMode mReliability; 162 // Incoming streams get queued here. Use a TArray though it's working as 163 // a FIFO - rarely will there be more than one entry in these arrays, so 164 // the overhead of mozilla::Queue is unneeded 165 nsTArray<std::tuple<uint64_t, RefPtr<mozilla::ipc::DataPipeReceiver>>> 166 mUnidirectionalStreams; 167 nsTArray<std::tuple<uint64_t, UniquePtr<BidirectionalPair>>> 168 mBidirectionalStreams; 169 170 // These are created in the constructor 171 RefPtr<ReadableStream> mIncomingUnidirectionalStreams; 172 RefPtr<ReadableStream> mIncomingBidirectionalStreams; 173 RefPtr<WebTransportDatagramDuplexStream> mDatagrams; 174 RefPtr<Promise> mClosed; 175 }; 176 177 } // namespace mozilla::dom 178 179 #endif // DOM_WEBTRANSPORT_API_WEBTRANSPORT__H_