diff options
Diffstat (limited to 'third_party/libwebrtc/net/dcsctp/tx/retransmission_timeout.cc')
-rw-r--r-- | third_party/libwebrtc/net/dcsctp/tx/retransmission_timeout.cc | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/third_party/libwebrtc/net/dcsctp/tx/retransmission_timeout.cc b/third_party/libwebrtc/net/dcsctp/tx/retransmission_timeout.cc new file mode 100644 index 0000000000..7d8fb9761c --- /dev/null +++ b/third_party/libwebrtc/net/dcsctp/tx/retransmission_timeout.cc @@ -0,0 +1,63 @@ +/* + * 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. + */ +#include "net/dcsctp/tx/retransmission_timeout.h" + +#include <algorithm> +#include <cstdint> + +#include "net/dcsctp/public/dcsctp_options.h" + +namespace dcsctp { + +RetransmissionTimeout::RetransmissionTimeout(const DcSctpOptions& options) + : min_rto_(*options.rto_min), + max_rto_(*options.rto_max), + max_rtt_(*options.rtt_max), + min_rtt_variance_(*options.min_rtt_variance), + scaled_srtt_(*options.rto_initial << kRttShift), + rto_(*options.rto_initial) {} + +void RetransmissionTimeout::ObserveRTT(DurationMs measured_rtt) { + const int32_t rtt = *measured_rtt; + + // Unrealistic values will be skipped. If a wrongly measured (or otherwise + // corrupt) value was processed, it could change the state in a way that would + // take a very long time to recover. + if (rtt < 0 || rtt > max_rtt_) { + return; + } + + // From https://tools.ietf.org/html/rfc4960#section-6.3.1, but avoiding + // floating point math by implementing algorithm from "V. Jacobson: Congestion + // avoidance and control", but adapted for SCTP. + if (first_measurement_) { + scaled_srtt_ = rtt << kRttShift; + scaled_rtt_var_ = (rtt / 2) << kRttVarShift; + first_measurement_ = false; + } else { + int32_t rtt_diff = rtt - (scaled_srtt_ >> kRttShift); + scaled_srtt_ += rtt_diff; + if (rtt_diff < 0) { + rtt_diff = -rtt_diff; + } + rtt_diff -= (scaled_rtt_var_ >> kRttVarShift); + scaled_rtt_var_ += rtt_diff; + } + + if (scaled_rtt_var_ < min_rtt_variance_) { + scaled_rtt_var_ = min_rtt_variance_; + } + + rto_ = (scaled_srtt_ >> kRttShift) + scaled_rtt_var_; + + // Clamp RTO between min and max. + rto_ = std::min(std::max(rto_, min_rto_), max_rto_); +} +} // namespace dcsctp |