tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Http2WebTransportSession.h (8185B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef mozilla_net_Http2WebTransportSession_h
      7 #define mozilla_net_Http2WebTransportSession_h
      8 
      9 #include "CapsuleParser.h"
     10 #include "Http2StreamTunnel.h"
     11 #include "mozilla/UniquePtr.h"
     12 #include "mozilla/Queue.h"
     13 #include "nsRefPtrHashtable.h"
     14 #include "nsTHashMap.h"
     15 #include "nsHashKeys.h"
     16 #include "WebTransportFlowControl.h"
     17 #include "WebTransportSessionBase.h"
     18 #include "WebTransportStreamBase.h"
     19 
     20 namespace mozilla::net {
     21 
     22 class CapsuleEncoder;
     23 class Http2WebTransportStream;
     24 
     25 // A handler used exclusively by Http2WebTransportSessionImpl for capsule I/O,
     26 // primarily responsible for sending capsules.
     27 class CapsuleIOHandler {
     28 public:
     29  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
     30 
     31  virtual void HasCapsuleToSend() = 0;
     32  virtual void SetSentFin() = 0;
     33  virtual void StartReading() = 0;
     34  virtual void OnCapsuleParseFailure(nsresult aError) = 0;
     35 
     36 protected:
     37  virtual ~CapsuleIOHandler() = default;
     38 };
     39 
     40 struct Http2WebTransportInitialSettings {
     41  // Initial session-level data limit.
     42  uint32_t mInitialMaxData = 0;
     43  // Initial stream-level data limit for outgoing unidirectional streams.
     44  uint32_t mInitialMaxStreamDataUni = 0;
     45  // Initial stream-level data limit for outgoing bidirectional streams.
     46  uint32_t mInitialMaxStreamDataBidi = 0;
     47  // Initial max unidirectional streams per session.
     48  uint32_t mInitialMaxStreamsUni = 0;
     49  // Initial max bidirectional streams per session.
     50  uint32_t mInitialMaxStreamsBidi = 0;
     51  // Initial limit on unidirectional streams that the peer creates.
     52  uint32_t mInitialLocalMaxStreamsUnidi = 16;
     53  // Initial limit on bidirectional streams that the peer creates.
     54  uint32_t mInitialLocalMaxStreamsBidi = 16;
     55  // Initial flow control limit for receiving data on unidirectional streams
     56  // that the peer creates.
     57  uint32_t mInitialLocalMaxStreamDataUnidi = 0x100000;
     58  // Initial flow control limit for receiving data on bidirectional streams
     59  // that the peer creates.
     60  uint32_t mInitialLocalMaxStreamDataBidi = 0x100000;
     61  // Initial session-level flow control limit.
     62  uint64_t mInitialLocalMaxData = 0x3FFFFFFFFFFFFFFF;
     63 };
     64 
     65 enum class CapsuleTransmissionPriority : uint8_t {
     66  Critical = 0,
     67  Important = 1,
     68  High = 2,
     69  Normal = 3,
     70  Low = 4,
     71 };
     72 
     73 // Core implementation of the logic behind Http2WebTransportSession.
     74 // It's designed to be independently instantiated, which makes it easier to
     75 // test.
     76 class Http2WebTransportSessionImpl final : public WebTransportSessionBase,
     77                                           public CapsuleParser::Listener {
     78 public:
     79  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Http2WebTransportSessionImpl, override)
     80 
     81  explicit Http2WebTransportSessionImpl(
     82      CapsuleIOHandler* aHandler, Http2WebTransportInitialSettings aSettings);
     83 
     84  void CloseSession(uint32_t aStatus, const nsACString& aReason) override;
     85  uint64_t GetStreamId() const override;
     86  void GetMaxDatagramSize() override;
     87  void SendDatagram(nsTArray<uint8_t>&& aData, uint64_t aTrackingId) override;
     88  void CreateOutgoingBidirectionalStream(
     89      std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&&
     90          aCallback) override;
     91  void CreateOutgoingUnidirectionalStream(
     92      std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&&
     93          aCallback) override;
     94  bool OnCapsule(Capsule&& aCapsule) override;
     95  void OnCapsuleParseFailure(nsresult aError) override;
     96  void StartReading() override;
     97  void Close(nsresult aReason);
     98 
     99  void OnStreamClosed(Http2WebTransportStream* aStream);
    100  void PrepareCapsulesToSend(
    101      mozilla::Queue<UniquePtr<CapsuleEncoder>>& aOutput);
    102  SenderFlowControlSession& SessionDataFc() { return mSessionDataFc; }
    103  ReceiverFlowControlSession& ReceiverFc() { return mReceiverFc; }
    104 
    105  void StreamHasCapsuleToSend();
    106  void OnStreamDataSent(StreamId aId, size_t aCount);
    107  void OnError(uint64_t aError);
    108 
    109 private:
    110  virtual ~Http2WebTransportSessionImpl();
    111 
    112  void CreateOutgoingStreamInternal(
    113      StreamId aStreamId,
    114      std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&&
    115          aCallback);
    116 
    117  class PendingStreamCallback {
    118   public:
    119    explicit PendingStreamCallback(
    120        std::function<void(
    121            Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&& aCallback)
    122        : mCallback(std::move(aCallback)) {}
    123    std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>
    124    TakeCallback() {
    125      return std::move(mCallback);
    126    }
    127 
    128   private:
    129    std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>
    130        mCallback;
    131  };
    132  void ProcessPendingStreamCallbacks(
    133      mozilla::Queue<UniquePtr<PendingStreamCallback>>& aCallbacks,
    134      WebTransportStreamType aStreamType);
    135  bool ProcessIncomingStreamCapsule(Capsule&& aCapsule, StreamId aID,
    136                                    WebTransportStreamType aStreamType);
    137  void SendMaintenanceCapsules(CapsuleTransmissionPriority aPriority);
    138  already_AddRefed<Http2WebTransportStream> GetStream(StreamId aId);
    139  bool HandleMaxStreamDataCapsule(StreamId aId, Capsule&& aCapsule);
    140  bool HandleStreamStopSendingCapsule(StreamId aId, Capsule&& aCapsule);
    141  bool HandleStreamResetCapsule(StreamId aId, Capsule&& aCapsule);
    142 
    143  class CapsuleQueue final {
    144   public:
    145    CapsuleQueue();
    146    mozilla::Queue<UniquePtr<CapsuleEncoder>>& operator[](
    147        CapsuleTransmissionPriority aPriority);
    148 
    149   private:
    150    mozilla::Queue<UniquePtr<CapsuleEncoder>> mCritical;
    151    mozilla::Queue<UniquePtr<CapsuleEncoder>> mImportant;
    152    mozilla::Queue<UniquePtr<CapsuleEncoder>> mHigh;
    153    mozilla::Queue<UniquePtr<CapsuleEncoder>> mNormal;
    154    mozilla::Queue<UniquePtr<CapsuleEncoder>> mLow;
    155  };
    156  void EnqueueOutCapsule(CapsuleTransmissionPriority aPriority,
    157                         UniquePtr<CapsuleEncoder>&& aData);
    158 
    159  uint64_t mStreamId = 0;
    160  nsRefPtrHashtable<nsUint64HashKey, Http2WebTransportStream> mOutgoingStreams;
    161  nsRefPtrHashtable<nsUint64HashKey, Http2WebTransportStream> mIncomingStreams;
    162 
    163  mozilla::Queue<UniquePtr<PendingStreamCallback>> mBidiPendingStreamCallbacks;
    164  mozilla::Queue<UniquePtr<PendingStreamCallback>> mUnidiPendingStreamCallbacks;
    165  Http2WebTransportInitialSettings mSettings;
    166  LocalStreamLimits mLocalStreamsFlowControl;
    167  RemoteStreamLimits mRemoteStreamsFlowControl;
    168 
    169  RefPtr<CapsuleIOHandler> mHandler;
    170  CapsuleQueue mCapsuleQueue;
    171  SenderFlowControlSession mSessionDataFc;
    172  ReceiverFlowControlSession mReceiverFc;
    173 };
    174 
    175 class Http2WebTransportSession final : public Http2StreamTunnel,
    176                                       public nsIOutputStreamCallback,
    177                                       public nsIInputStreamCallback,
    178                                       public CapsuleIOHandler {
    179 public:
    180  NS_DECL_ISUPPORTS_INHERITED
    181  NS_DECL_NSIOUTPUTSTREAMCALLBACK
    182  NS_DECL_NSIINPUTSTREAMCALLBACK
    183 
    184  Http2WebTransportSession(Http2Session* aSession, int32_t aPriority,
    185                           uint64_t aBcId,
    186                           nsHttpConnectionInfo* aConnectionInfo,
    187                           Http2WebTransportInitialSettings aSettings);
    188  Http2WebTransportSession* GetHttp2WebTransportSession() override {
    189    return this;
    190  }
    191  Http2WebTransportSessionImpl* GetHttp2WebTransportSessionImpl() {
    192    return mImpl;
    193  }
    194 
    195  void CloseStream(nsresult aReason) override;
    196  void HasCapsuleToSend() override;
    197  void SetSentFin() override;
    198  void StartReading() override;
    199  void OnCapsuleParseFailure(nsresult aError) override;
    200 
    201 private:
    202  virtual ~Http2WebTransportSession();
    203  nsresult GenerateHeaders(nsCString& aCompressedData,
    204                           uint8_t& aFirstFrameFlags) override;
    205 
    206  size_t mWriteOffset{0};
    207  mozilla::Queue<UniquePtr<CapsuleEncoder>> mOutgoingQueue;
    208  RefPtr<Http2WebTransportSessionImpl> mImpl;
    209  UniquePtr<CapsuleParser> mCapsuleParser;
    210  UniquePtr<CapsuleEncoder> mCurrentOutCapsule;
    211 };
    212 
    213 }  // namespace mozilla::net
    214 
    215 #endif  // mozilla_net_Http2WebTransportSession_h