xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_MOQT_SUBSCRIBE_WINDOWS_H
6 #define QUICHE_QUIC_MOQT_SUBSCRIBE_WINDOWS_H
7 
8 #include <cstdint>
9 #include <optional>
10 #include <vector>
11 
12 #include "absl/container/flat_hash_map.h"
13 #include "absl/container/node_hash_map.h"
14 #include "quiche/quic/moqt/moqt_messages.h"
15 #include "quiche/common/platform/api/quiche_export.h"
16 #include "quiche/web_transport/web_transport.h"
17 
18 namespace moqt {
19 
20 // Classes to track subscriptions to local tracks: the sequence numbers
21 // subscribed, the streams involved, and the subscribe IDs.
22 class QUICHE_EXPORT SubscribeWindow {
23  public:
24   // Creates a half-open window.
SubscribeWindow(uint64_t subscribe_id,MoqtForwardingPreference forwarding_preference,uint64_t start_group,uint64_t start_object)25   SubscribeWindow(uint64_t subscribe_id,
26                   MoqtForwardingPreference forwarding_preference,
27                   uint64_t start_group, uint64_t start_object)
28       : subscribe_id_(subscribe_id),
29         start_({start_group, start_object}),
30         forwarding_preference_(forwarding_preference) {}
31 
32   // Creates a closed window.
SubscribeWindow(uint64_t subscribe_id,MoqtForwardingPreference forwarding_preference,uint64_t start_group,uint64_t start_object,uint64_t end_group,uint64_t end_object)33   SubscribeWindow(uint64_t subscribe_id,
34                   MoqtForwardingPreference forwarding_preference,
35                   uint64_t start_group, uint64_t start_object,
36                   uint64_t end_group, uint64_t end_object)
37       : subscribe_id_(subscribe_id),
38         start_({start_group, start_object}),
39         end_(FullSequence(end_group, end_object)),
40         forwarding_preference_(forwarding_preference) {}
41 
subscribe_id()42   uint64_t subscribe_id() const { return subscribe_id_; }
43 
44   bool InWindow(const FullSequence& seq) const;
45 
46   // Returns the stream to send |sequence| on, if already opened.
47   std::optional<webtransport::StreamId> GetStreamForSequence(
48       FullSequence sequence) const;
49 
50   // Records what stream is being used for a track, group, or object depending
51   // on |forwarding_preference|. Triggers QUIC_BUG if already assigned.
52   void AddStream(uint64_t group_id, uint64_t object_id,
53                  webtransport::StreamId stream_id);
54 
55   void RemoveStream(uint64_t group_id, uint64_t object_id);
56 
57  private:
58   // Converts an object sequence number into one that matches the way that
59   // stream IDs are being mapped. (See the comment for send_streams_ below.)
60   FullSequence SequenceToIndex(FullSequence sequence) const;
61 
62   const uint64_t subscribe_id_;
63   const FullSequence start_;
64   const std::optional<FullSequence> end_ = std::nullopt;
65   // Store open streams for this subscription. If the forwarding preference is
66   // kTrack, there is one entry under sequence (0, 0). If kGroup, each entry is
67   // under (group, 0). If kObject, it's tracked under the full sequence. If
68   // kDatagram, the map is empty.
69   absl::flat_hash_map<FullSequence, webtransport::StreamId> send_streams_;
70   // The forwarding preference for this track; informs how the streams are
71   // mapped.
72   const MoqtForwardingPreference forwarding_preference_;
73 };
74 
75 // Class to keep track of the sequence number blocks to which a peer is
76 // subscribed.
77 class QUICHE_EXPORT MoqtSubscribeWindows {
78  public:
MoqtSubscribeWindows(MoqtForwardingPreference forwarding_preference)79   MoqtSubscribeWindows(MoqtForwardingPreference forwarding_preference)
80       : forwarding_preference_(forwarding_preference) {}
81 
82   // Returns a vector of subscribe IDs that apply to the object. They will be in
83   // reverse order of the AddWindow calls.
84   std::vector<SubscribeWindow*> SequenceIsSubscribed(FullSequence sequence);
85 
86   // |start_group| and |start_object| must be absolute sequence numbers. An
87   // optimization could consolidate overlapping subscribe windows.
AddWindow(uint64_t subscribe_id,uint64_t start_group,uint64_t start_object)88   void AddWindow(uint64_t subscribe_id, uint64_t start_group,
89                  uint64_t start_object) {
90     windows_.emplace(subscribe_id,
91                      SubscribeWindow(subscribe_id, forwarding_preference_,
92                                      start_group, start_object));
93   }
AddWindow(uint64_t subscribe_id,uint64_t start_group,uint64_t start_object,uint64_t end_group,uint64_t end_object)94   void AddWindow(uint64_t subscribe_id, uint64_t start_group,
95                  uint64_t start_object, uint64_t end_group,
96                  uint64_t end_object) {
97     windows_.emplace(
98         subscribe_id,
99         SubscribeWindow(subscribe_id, forwarding_preference_, start_group,
100                         start_object, end_group, end_object));
101   }
RemoveWindow(uint64_t subscribe_id)102   void RemoveWindow(uint64_t subscribe_id) { windows_.erase(subscribe_id); }
103 
IsEmpty()104   bool IsEmpty() const { return windows_.empty(); }
105 
GetWindow(uint64_t subscribe_id)106   SubscribeWindow* GetWindow(uint64_t subscribe_id) {
107     auto it = windows_.find(subscribe_id);
108     if (it == windows_.end()) {
109       return nullptr;
110     }
111     return &it->second;
112   }
113 
114  private:
115   // Indexed by Subscribe ID.
116   absl::node_hash_map<uint64_t, SubscribeWindow> windows_;
117   const MoqtForwardingPreference forwarding_preference_;
118 };
119 
120 }  // namespace moqt
121 
122 #endif  // QUICHE_QUIC_MOQT_SUBSCRIBE_WINDOWS_H
123