File: Http2WebTransportSession.h

package info (click to toggle)
firefox 147.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,320 kB
  • sloc: cpp: 7,607,359; javascript: 6,533,295; ansic: 3,775,223; python: 1,415,500; xml: 634,561; asm: 438,949; java: 186,241; sh: 62,752; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (215 lines) | stat: -rw-r--r-- 8,185 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_net_Http2WebTransportSession_h
#define mozilla_net_Http2WebTransportSession_h

#include "CapsuleParser.h"
#include "Http2StreamTunnel.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Queue.h"
#include "nsRefPtrHashtable.h"
#include "nsTHashMap.h"
#include "nsHashKeys.h"
#include "WebTransportFlowControl.h"
#include "WebTransportSessionBase.h"
#include "WebTransportStreamBase.h"

namespace mozilla::net {

class CapsuleEncoder;
class Http2WebTransportStream;

// A handler used exclusively by Http2WebTransportSessionImpl for capsule I/O,
// primarily responsible for sending capsules.
class CapsuleIOHandler {
 public:
  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING

  virtual void HasCapsuleToSend() = 0;
  virtual void SetSentFin() = 0;
  virtual void StartReading() = 0;
  virtual void OnCapsuleParseFailure(nsresult aError) = 0;

 protected:
  virtual ~CapsuleIOHandler() = default;
};

struct Http2WebTransportInitialSettings {
  // Initial session-level data limit.
  uint32_t mInitialMaxData = 0;
  // Initial stream-level data limit for outgoing unidirectional streams.
  uint32_t mInitialMaxStreamDataUni = 0;
  // Initial stream-level data limit for outgoing bidirectional streams.
  uint32_t mInitialMaxStreamDataBidi = 0;
  // Initial max unidirectional streams per session.
  uint32_t mInitialMaxStreamsUni = 0;
  // Initial max bidirectional streams per session.
  uint32_t mInitialMaxStreamsBidi = 0;
  // Initial limit on unidirectional streams that the peer creates.
  uint32_t mInitialLocalMaxStreamsUnidi = 16;
  // Initial limit on bidirectional streams that the peer creates.
  uint32_t mInitialLocalMaxStreamsBidi = 16;
  // Initial flow control limit for receiving data on unidirectional streams
  // that the peer creates.
  uint32_t mInitialLocalMaxStreamDataUnidi = 0x100000;
  // Initial flow control limit for receiving data on bidirectional streams
  // that the peer creates.
  uint32_t mInitialLocalMaxStreamDataBidi = 0x100000;
  // Initial session-level flow control limit.
  uint64_t mInitialLocalMaxData = 0x3FFFFFFFFFFFFFFF;
};

enum class CapsuleTransmissionPriority : uint8_t {
  Critical = 0,
  Important = 1,
  High = 2,
  Normal = 3,
  Low = 4,
};

// Core implementation of the logic behind Http2WebTransportSession.
// It's designed to be independently instantiated, which makes it easier to
// test.
class Http2WebTransportSessionImpl final : public WebTransportSessionBase,
                                           public CapsuleParser::Listener {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Http2WebTransportSessionImpl, override)

  explicit Http2WebTransportSessionImpl(
      CapsuleIOHandler* aHandler, Http2WebTransportInitialSettings aSettings);

  void CloseSession(uint32_t aStatus, const nsACString& aReason) override;
  uint64_t GetStreamId() const override;
  void GetMaxDatagramSize() override;
  void SendDatagram(nsTArray<uint8_t>&& aData, uint64_t aTrackingId) override;
  void CreateOutgoingBidirectionalStream(
      std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&&
          aCallback) override;
  void CreateOutgoingUnidirectionalStream(
      std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&&
          aCallback) override;
  bool OnCapsule(Capsule&& aCapsule) override;
  void OnCapsuleParseFailure(nsresult aError) override;
  void StartReading() override;
  void Close(nsresult aReason);

  void OnStreamClosed(Http2WebTransportStream* aStream);
  void PrepareCapsulesToSend(
      mozilla::Queue<UniquePtr<CapsuleEncoder>>& aOutput);
  SenderFlowControlSession& SessionDataFc() { return mSessionDataFc; }
  ReceiverFlowControlSession& ReceiverFc() { return mReceiverFc; }

  void StreamHasCapsuleToSend();
  void OnStreamDataSent(StreamId aId, size_t aCount);
  void OnError(uint64_t aError);

 private:
  virtual ~Http2WebTransportSessionImpl();

  void CreateOutgoingStreamInternal(
      StreamId aStreamId,
      std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&&
          aCallback);

  class PendingStreamCallback {
   public:
    explicit PendingStreamCallback(
        std::function<void(
            Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>&& aCallback)
        : mCallback(std::move(aCallback)) {}
    std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>
    TakeCallback() {
      return std::move(mCallback);
    }

   private:
    std::function<void(Result<RefPtr<WebTransportStreamBase>, nsresult>&&)>
        mCallback;
  };
  void ProcessPendingStreamCallbacks(
      mozilla::Queue<UniquePtr<PendingStreamCallback>>& aCallbacks,
      WebTransportStreamType aStreamType);
  bool ProcessIncomingStreamCapsule(Capsule&& aCapsule, StreamId aID,
                                    WebTransportStreamType aStreamType);
  void SendMaintenanceCapsules(CapsuleTransmissionPriority aPriority);
  already_AddRefed<Http2WebTransportStream> GetStream(StreamId aId);
  bool HandleMaxStreamDataCapsule(StreamId aId, Capsule&& aCapsule);
  bool HandleStreamStopSendingCapsule(StreamId aId, Capsule&& aCapsule);
  bool HandleStreamResetCapsule(StreamId aId, Capsule&& aCapsule);

  class CapsuleQueue final {
   public:
    CapsuleQueue();
    mozilla::Queue<UniquePtr<CapsuleEncoder>>& operator[](
        CapsuleTransmissionPriority aPriority);

   private:
    mozilla::Queue<UniquePtr<CapsuleEncoder>> mCritical;
    mozilla::Queue<UniquePtr<CapsuleEncoder>> mImportant;
    mozilla::Queue<UniquePtr<CapsuleEncoder>> mHigh;
    mozilla::Queue<UniquePtr<CapsuleEncoder>> mNormal;
    mozilla::Queue<UniquePtr<CapsuleEncoder>> mLow;
  };
  void EnqueueOutCapsule(CapsuleTransmissionPriority aPriority,
                         UniquePtr<CapsuleEncoder>&& aData);

  uint64_t mStreamId = 0;
  nsRefPtrHashtable<nsUint64HashKey, Http2WebTransportStream> mOutgoingStreams;
  nsRefPtrHashtable<nsUint64HashKey, Http2WebTransportStream> mIncomingStreams;

  mozilla::Queue<UniquePtr<PendingStreamCallback>> mBidiPendingStreamCallbacks;
  mozilla::Queue<UniquePtr<PendingStreamCallback>> mUnidiPendingStreamCallbacks;
  Http2WebTransportInitialSettings mSettings;
  LocalStreamLimits mLocalStreamsFlowControl;
  RemoteStreamLimits mRemoteStreamsFlowControl;

  RefPtr<CapsuleIOHandler> mHandler;
  CapsuleQueue mCapsuleQueue;
  SenderFlowControlSession mSessionDataFc;
  ReceiverFlowControlSession mReceiverFc;
};

class Http2WebTransportSession final : public Http2StreamTunnel,
                                       public nsIOutputStreamCallback,
                                       public nsIInputStreamCallback,
                                       public CapsuleIOHandler {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSIOUTPUTSTREAMCALLBACK
  NS_DECL_NSIINPUTSTREAMCALLBACK

  Http2WebTransportSession(Http2Session* aSession, int32_t aPriority,
                           uint64_t aBcId,
                           nsHttpConnectionInfo* aConnectionInfo,
                           Http2WebTransportInitialSettings aSettings);
  Http2WebTransportSession* GetHttp2WebTransportSession() override {
    return this;
  }
  Http2WebTransportSessionImpl* GetHttp2WebTransportSessionImpl() {
    return mImpl;
  }

  void CloseStream(nsresult aReason) override;
  void HasCapsuleToSend() override;
  void SetSentFin() override;
  void StartReading() override;
  void OnCapsuleParseFailure(nsresult aError) override;

 private:
  virtual ~Http2WebTransportSession();
  nsresult GenerateHeaders(nsCString& aCompressedData,
                           uint8_t& aFirstFrameFlags) override;

  size_t mWriteOffset{0};
  mozilla::Queue<UniquePtr<CapsuleEncoder>> mOutgoingQueue;
  RefPtr<Http2WebTransportSessionImpl> mImpl;
  UniquePtr<CapsuleParser> mCapsuleParser;
  UniquePtr<CapsuleEncoder> mCurrentOutCapsule;
};

}  // namespace mozilla::net

#endif  // mozilla_net_Http2WebTransportSession_h