/* * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef NET_DCSCTP_SOCKET_TRANSMISSION_CONTROL_BLOCK_H_ #define NET_DCSCTP_SOCKET_TRANSMISSION_CONTROL_BLOCK_H_ #include #include #include #include #include #include #include "absl/functional/bind_front.h" #include "absl/strings/string_view.h" #include "api/task_queue/task_queue_base.h" #include "net/dcsctp/common/sequence_numbers.h" #include "net/dcsctp/packet/chunk/cookie_echo_chunk.h" #include "net/dcsctp/packet/sctp_packet.h" #include "net/dcsctp/public/dcsctp_options.h" #include "net/dcsctp/public/dcsctp_socket.h" #include "net/dcsctp/rx/data_tracker.h" #include "net/dcsctp/rx/reassembly_queue.h" #include "net/dcsctp/socket/capabilities.h" #include "net/dcsctp/socket/context.h" #include "net/dcsctp/socket/heartbeat_handler.h" #include "net/dcsctp/socket/packet_sender.h" #include "net/dcsctp/socket/stream_reset_handler.h" #include "net/dcsctp/timer/timer.h" #include "net/dcsctp/tx/retransmission_error_counter.h" #include "net/dcsctp/tx/retransmission_queue.h" #include "net/dcsctp/tx/retransmission_timeout.h" #include "net/dcsctp/tx/send_queue.h" namespace dcsctp { // The TransmissionControlBlock (TCB) represents an open connection to a peer, // and holds all the resources for that. If the connection is e.g. shutdown, // closed or restarted, this object will be deleted and/or replaced. class TransmissionControlBlock : public Context { public: TransmissionControlBlock(TimerManager& timer_manager, absl::string_view log_prefix, const DcSctpOptions& options, const Capabilities& capabilities, DcSctpSocketCallbacks& callbacks, SendQueue& send_queue, VerificationTag my_verification_tag, TSN my_initial_tsn, VerificationTag peer_verification_tag, TSN peer_initial_tsn, size_t a_rwnd, TieTag tie_tag, PacketSender& packet_sender, std::function is_connection_established); // Implementation of `Context`. bool is_connection_established() const override { return is_connection_established_(); } TSN my_initial_tsn() const override { return my_initial_tsn_; } TSN peer_initial_tsn() const override { return peer_initial_tsn_; } DcSctpSocketCallbacks& callbacks() const override { return callbacks_; } void ObserveRTT(webrtc::TimeDelta rtt) override; webrtc::TimeDelta current_rto() const override { return rto_.rto(); } bool IncrementTxErrorCounter(absl::string_view reason) override { return tx_error_counter_.Increment(reason); } void ClearTxErrorCounter() override { tx_error_counter_.Clear(); } SctpPacket::Builder PacketBuilder() const override { return SctpPacket::Builder(peer_verification_tag_, options_); } bool HasTooManyTxErrors() const override { return tx_error_counter_.IsExhausted(); } void Send(SctpPacket::Builder& builder) override { packet_sender_.Send(builder, /*write_checksum=*/!capabilities_.zero_checksum); } // Other accessors DataTracker& data_tracker() { return data_tracker_; } ReassemblyQueue& reassembly_queue() { return reassembly_queue_; } RetransmissionQueue& retransmission_queue() { return retransmission_queue_; } StreamResetHandler& stream_reset_handler() { return stream_reset_handler_; } HeartbeatHandler& heartbeat_handler() { return heartbeat_handler_; } size_t cwnd() const { return retransmission_queue_.cwnd(); } webrtc::TimeDelta current_srtt() const { return rto_.srtt(); } // Returns this socket's verification tag, set in all packet headers. VerificationTag my_verification_tag() const { return my_verification_tag_; } // Returns the peer's verification tag, which should be in received packets. VerificationTag peer_verification_tag() const { return peer_verification_tag_; } // All negotiated supported capabilities. const Capabilities& capabilities() const { return capabilities_; } // A 64-bit tie-tag, used to e.g. detect reconnections. TieTag tie_tag() const { return tie_tag_; } // Sends a SACK, if there is a need to. void MaybeSendSack(); // Sends a FORWARD-TSN, if it is needed and allowed (rate-limited). void MaybeSendForwardTsn(SctpPacket::Builder& builder, webrtc::Timestamp now); // Will be set while the socket is in kCookieEcho state. In this state, there // can only be a single packet outstanding, and it must contain the COOKIE // ECHO chunk as the first chunk in that packet, until the COOKIE ACK has been // received, which will make the socket call `ClearCookieEchoChunk`. void SetCookieEchoChunk(CookieEchoChunk chunk) { cookie_echo_chunk_ = std::move(chunk); } // Called when the COOKIE ACK chunk has been received, to allow further // packets to be sent. void ClearCookieEchoChunk() { cookie_echo_chunk_ = absl::nullopt; } bool has_cookie_echo_chunk() const { return cookie_echo_chunk_.has_value(); } void MaybeSendFastRetransmit(); // Fills `builder` (which may already be filled with control chunks) with // other control and data chunks, and sends packets as much as can be // allowed by the congestion control algorithm. void SendBufferedPackets(SctpPacket::Builder& builder, webrtc::Timestamp now); // As above, but without passing in a builder. If `cookie_echo_chunk_` is // present, then only one packet will be sent, with this chunk as the first // chunk. void SendBufferedPackets(webrtc::Timestamp now) { SctpPacket::Builder builder(peer_verification_tag_, options_); SendBufferedPackets(builder, now); } // Returns a textual representation of this object, for logging. std::string ToString() const; HandoverReadinessStatus GetHandoverReadiness() const; void AddHandoverState(DcSctpSocketHandoverState& state); void RestoreFromState(const DcSctpSocketHandoverState& handover_state); private: // Will be called when the retransmission timer (t3-rtx) expires. webrtc::TimeDelta OnRtxTimerExpiry(); // Will be called when the delayed ack timer expires. webrtc::TimeDelta OnDelayedAckTimerExpiry(); const absl::string_view log_prefix_; const DcSctpOptions options_; TimerManager& timer_manager_; // Negotiated capabilities that both peers support. const Capabilities capabilities_; DcSctpSocketCallbacks& callbacks_; // The data retransmission timer, called t3-rtx in SCTP. const std::unique_ptr t3_rtx_; // Delayed ack timer, which triggers when acks should be sent (when delayed). const std::unique_ptr delayed_ack_timer_; const VerificationTag my_verification_tag_; const TSN my_initial_tsn_; const VerificationTag peer_verification_tag_; const TSN peer_initial_tsn_; // Nonce, used to detect reconnections. const TieTag tie_tag_; const std::function is_connection_established_; PacketSender& packet_sender_; // Rate limiting of FORWARD-TSN. Next can be sent at or after this timestamp. webrtc::Timestamp limit_forward_tsn_until_ = webrtc::Timestamp::Zero(); RetransmissionTimeout rto_; RetransmissionErrorCounter tx_error_counter_; DataTracker data_tracker_; ReassemblyQueue reassembly_queue_; RetransmissionQueue retransmission_queue_; StreamResetHandler stream_reset_handler_; HeartbeatHandler heartbeat_handler_; // Only valid when the socket state == State::kCookieEchoed. In this state, // the socket must wait for COOKIE ACK to continue sending any packets (not // including a COOKIE ECHO). So if `cookie_echo_chunk_` is present, the // SendBufferedChunks will always only just send one packet, with this chunk // as the first chunk in the packet. absl::optional cookie_echo_chunk_ = absl::nullopt; }; } // namespace dcsctp #endif // NET_DCSCTP_SOCKET_TRANSMISSION_CONTROL_BLOCK_H_