xref: /aosp_15_r20/external/webrtc/net/dcsctp/socket/stream_reset_handler.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #ifndef NET_DCSCTP_SOCKET_STREAM_RESET_HANDLER_H_
11 #define NET_DCSCTP_SOCKET_STREAM_RESET_HANDLER_H_
12 
13 #include <cstdint>
14 #include <memory>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 #include "absl/functional/bind_front.h"
20 #include "absl/strings/string_view.h"
21 #include "absl/types/optional.h"
22 #include "api/array_view.h"
23 #include "net/dcsctp/common/internal_types.h"
24 #include "net/dcsctp/packet/chunk/reconfig_chunk.h"
25 #include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
26 #include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
27 #include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
28 #include "net/dcsctp/packet/sctp_packet.h"
29 #include "net/dcsctp/public/dcsctp_socket.h"
30 #include "net/dcsctp/rx/data_tracker.h"
31 #include "net/dcsctp/rx/reassembly_queue.h"
32 #include "net/dcsctp/socket/context.h"
33 #include "net/dcsctp/timer/timer.h"
34 #include "net/dcsctp/tx/retransmission_queue.h"
35 #include "rtc_base/containers/flat_set.h"
36 
37 namespace dcsctp {
38 
39 // StreamResetHandler handles sending outgoing stream reset requests (to close
40 // an SCTP stream, which translates to closing a data channel).
41 //
42 // It also handles incoming "outgoing stream reset requests", when the peer
43 // wants to close its data channel.
44 //
45 // Resetting streams is an asynchronous operation where the client will request
46 // a request a stream to be reset, but then it might not be performed exactly at
47 // this point. First, the sender might need to discard all messages that have
48 // been enqueued for this stream, or it may select to wait until all have been
49 // sent. At least, it must wait for the currently sending fragmented message to
50 // be fully sent, because a stream can't be reset while having received half a
51 // message. In the stream reset request, the "sender's last assigned TSN" is
52 // provided, which is simply the TSN for which the receiver should've received
53 // all messages before this value, before the stream can be reset. Since
54 // fragments can get lost or sent out-of-order, the receiver of a request may
55 // not have received all the data just yet, and then it will respond to the
56 // sender: "In progress". In other words, try again. The sender will then need
57 // to start a timer and try the very same request again (but with a new sequence
58 // number) until the receiver successfully performs the operation.
59 //
60 // All this can take some time, and may be driven by timers, so the client will
61 // ultimately be notified using callbacks.
62 //
63 // In this implementation, when a stream is reset, the queued but not-yet-sent
64 // messages will be discarded, but that may change in the future. RFC8831 allows
65 // both behaviors.
66 class StreamResetHandler {
67  public:
68   StreamResetHandler(absl::string_view log_prefix,
69                      Context* context,
70                      TimerManager* timer_manager,
71                      DataTracker* data_tracker,
72                      ReassemblyQueue* reassembly_queue,
73                      RetransmissionQueue* retransmission_queue,
74                      const DcSctpSocketHandoverState* handover_state = nullptr)
75       : log_prefix_(std::string(log_prefix) + "reset: "),
76         ctx_(context),
77         data_tracker_(data_tracker),
78         reassembly_queue_(reassembly_queue),
79         retransmission_queue_(retransmission_queue),
80         reconfig_timer_(timer_manager->CreateTimer(
81             "re-config",
82             absl::bind_front(&StreamResetHandler::OnReconfigTimerExpiry, this),
83             TimerOptions(DurationMs(0)))),
84         next_outgoing_req_seq_nbr_(
85             handover_state
86                 ? ReconfigRequestSN(handover_state->tx.next_reset_req_sn)
87                 : ReconfigRequestSN(*ctx_->my_initial_tsn())),
88         last_processed_req_seq_nbr_(
89             handover_state ? ReconfigRequestSN(
90                                  handover_state->rx.last_completed_reset_req_sn)
91                            : ReconfigRequestSN(*ctx_->peer_initial_tsn() - 1)),
92         last_processed_req_result_(
93             ReconfigurationResponseParameter::Result::kSuccessNothingToDo) {}
94 
95   // Initiates reset of the provided streams. While there can only be one
96   // ongoing stream reset request at any time, this method can be called at any
97   // time and also multiple times. It will enqueue requests that can't be
98   // directly fulfilled, and will asynchronously process them when any ongoing
99   // request has completed.
100   void ResetStreams(rtc::ArrayView<const StreamID> outgoing_streams);
101 
102   // Creates a Reset Streams request that must be sent if returned. Will start
103   // the reconfig timer. Will return absl::nullopt if there is no need to
104   // create a request (no streams to reset) or if there already is an ongoing
105   // stream reset request that hasn't completed yet.
106   absl::optional<ReConfigChunk> MakeStreamResetRequest();
107 
108   // Called when handling and incoming RE-CONFIG chunk.
109   void HandleReConfig(ReConfigChunk chunk);
110 
111   HandoverReadinessStatus GetHandoverReadiness() const;
112 
113   void AddHandoverState(DcSctpSocketHandoverState& state);
114 
115  private:
116   // Represents a stream request operation. There can only be one ongoing at
117   // any time, and a sent request may either succeed, fail or result in the
118   // receiver signaling that it can't process it right now, and then it will be
119   // retried.
120   class CurrentRequest {
121    public:
CurrentRequest(TSN sender_last_assigned_tsn,std::vector<StreamID> streams)122     CurrentRequest(TSN sender_last_assigned_tsn, std::vector<StreamID> streams)
123         : req_seq_nbr_(absl::nullopt),
124           sender_last_assigned_tsn_(sender_last_assigned_tsn),
125           streams_(std::move(streams)) {}
126 
127     // Returns the current request sequence number, if this request has been
128     // sent (check `has_been_sent` first). Will return 0 if the request is just
129     // prepared (or scheduled for retransmission) but not yet sent.
req_seq_nbr()130     ReconfigRequestSN req_seq_nbr() const {
131       return req_seq_nbr_.value_or(ReconfigRequestSN(0));
132     }
133 
134     // The sender's last assigned TSN, from the retransmission queue. The
135     // receiver uses this to know when all data up to this TSN has been
136     // received, to know when to safely reset the stream.
sender_last_assigned_tsn()137     TSN sender_last_assigned_tsn() const { return sender_last_assigned_tsn_; }
138 
139     // The streams that are to be reset.
streams()140     const std::vector<StreamID>& streams() const { return streams_; }
141 
142     // If this request has been sent yet. If not, then it's either because it
143     // has only been prepared and not yet sent, or because the received couldn't
144     // apply the request, and then the exact same request will be retried, but
145     // with a new sequence number.
has_been_sent()146     bool has_been_sent() const { return req_seq_nbr_.has_value(); }
147 
148     // If the receiver can't apply the request yet (and answered "In Progress"),
149     // this will be called to prepare the request to be retransmitted at a later
150     // time.
PrepareRetransmission()151     void PrepareRetransmission() { req_seq_nbr_ = absl::nullopt; }
152 
153     // If the request hasn't been sent yet, this assigns it a request number.
PrepareToSend(ReconfigRequestSN new_req_seq_nbr)154     void PrepareToSend(ReconfigRequestSN new_req_seq_nbr) {
155       req_seq_nbr_ = new_req_seq_nbr;
156     }
157 
158    private:
159     // If this is set, this request has been sent. If it's not set, the request
160     // has been prepared, but has not yet been sent. This is typically used when
161     // the peer responded "in progress" and the same request (but a different
162     // request number) must be sent again.
163     absl::optional<ReconfigRequestSN> req_seq_nbr_;
164     // The sender's (that's us) last assigned TSN, from the retransmission
165     // queue.
166     TSN sender_last_assigned_tsn_;
167     // The streams that are to be reset in this request.
168     const std::vector<StreamID> streams_;
169   };
170 
171   // Called to validate an incoming RE-CONFIG chunk.
172   bool Validate(const ReConfigChunk& chunk);
173 
174   // Processes a stream stream reconfiguration chunk and may either return
175   // absl::nullopt (on protocol errors), or a list of responses - either 0, 1
176   // or 2.
177   absl::optional<std::vector<ReconfigurationResponseParameter>> Process(
178       const ReConfigChunk& chunk);
179 
180   // Creates the actual RE-CONFIG chunk. A request (which set `current_request`)
181   // must have been created prior.
182   ReConfigChunk MakeReconfigChunk();
183 
184   // Called to validate the `req_seq_nbr`, that it's the next in sequence. If it
185   // fails to validate, and returns false, it will also add a response to
186   // `responses`.
187   bool ValidateReqSeqNbr(
188       ReconfigRequestSN req_seq_nbr,
189       std::vector<ReconfigurationResponseParameter>& responses);
190 
191   // Called when this socket receives an outgoing stream reset request. It might
192   // either be performed straight away, or have to be deferred, and the result
193   // of that will be put in `responses`.
194   void HandleResetOutgoing(
195       const ParameterDescriptor& descriptor,
196       std::vector<ReconfigurationResponseParameter>& responses);
197 
198   // Called when this socket receives an incoming stream reset request. This
199   // isn't really supported, but a successful response is put in `responses`.
200   void HandleResetIncoming(
201       const ParameterDescriptor& descriptor,
202       std::vector<ReconfigurationResponseParameter>& responses);
203 
204   // Called when receiving a response to an outgoing stream reset request. It
205   // will either commit the stream resetting, if the operation was successful,
206   // or will schedule a retry if it was deferred. And if it failed, the
207   // operation will be rolled back.
208   void HandleResponse(const ParameterDescriptor& descriptor);
209 
210   // Expiration handler for the Reconfig timer.
211   absl::optional<DurationMs> OnReconfigTimerExpiry();
212 
213   const std::string log_prefix_;
214   Context* ctx_;
215   DataTracker* data_tracker_;
216   ReassemblyQueue* reassembly_queue_;
217   RetransmissionQueue* retransmission_queue_;
218   const std::unique_ptr<Timer> reconfig_timer_;
219 
220   // The next sequence number for outgoing stream requests.
221   ReconfigRequestSN next_outgoing_req_seq_nbr_;
222 
223   // The current stream request operation.
224   absl::optional<CurrentRequest> current_request_;
225 
226   // For incoming requests - last processed request sequence number.
227   ReconfigRequestSN last_processed_req_seq_nbr_;
228   // The result from last processed incoming request
229   ReconfigurationResponseParameter::Result last_processed_req_result_;
230 };
231 }  // namespace dcsctp
232 
233 #endif  // NET_DCSCTP_SOCKET_STREAM_RESET_HANDLER_H_
234