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