1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker #ifndef NET_DCSCTP_TIMER_FAKE_TIMEOUT_H_ 11*d9f75844SAndroid Build Coastguard Worker #define NET_DCSCTP_TIMER_FAKE_TIMEOUT_H_ 12*d9f75844SAndroid Build Coastguard Worker 13*d9f75844SAndroid Build Coastguard Worker #include <cstdint> 14*d9f75844SAndroid Build Coastguard Worker #include <functional> 15*d9f75844SAndroid Build Coastguard Worker #include <limits> 16*d9f75844SAndroid Build Coastguard Worker #include <memory> 17*d9f75844SAndroid Build Coastguard Worker #include <utility> 18*d9f75844SAndroid Build Coastguard Worker #include <vector> 19*d9f75844SAndroid Build Coastguard Worker 20*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h" 21*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h" 22*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/public/timeout.h" 23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h" 24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/containers/flat_set.h" 25*d9f75844SAndroid Build Coastguard Worker 26*d9f75844SAndroid Build Coastguard Worker namespace dcsctp { 27*d9f75844SAndroid Build Coastguard Worker 28*d9f75844SAndroid Build Coastguard Worker // A timeout used in tests. 29*d9f75844SAndroid Build Coastguard Worker class FakeTimeout : public Timeout { 30*d9f75844SAndroid Build Coastguard Worker public: FakeTimeout(std::function<TimeMs ()> get_time,std::function<void (FakeTimeout *)> on_delete)31*d9f75844SAndroid Build Coastguard Worker FakeTimeout(std::function<TimeMs()> get_time, 32*d9f75844SAndroid Build Coastguard Worker std::function<void(FakeTimeout*)> on_delete) 33*d9f75844SAndroid Build Coastguard Worker : get_time_(std::move(get_time)), on_delete_(std::move(on_delete)) {} 34*d9f75844SAndroid Build Coastguard Worker ~FakeTimeout()35*d9f75844SAndroid Build Coastguard Worker ~FakeTimeout() override { on_delete_(this); } 36*d9f75844SAndroid Build Coastguard Worker Start(DurationMs duration_ms,TimeoutID timeout_id)37*d9f75844SAndroid Build Coastguard Worker void Start(DurationMs duration_ms, TimeoutID timeout_id) override { 38*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(expiry_ == TimeMs::InfiniteFuture()); 39*d9f75844SAndroid Build Coastguard Worker timeout_id_ = timeout_id; 40*d9f75844SAndroid Build Coastguard Worker expiry_ = get_time_() + duration_ms; 41*d9f75844SAndroid Build Coastguard Worker } Stop()42*d9f75844SAndroid Build Coastguard Worker void Stop() override { 43*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(expiry_ != TimeMs::InfiniteFuture()); 44*d9f75844SAndroid Build Coastguard Worker expiry_ = TimeMs::InfiniteFuture(); 45*d9f75844SAndroid Build Coastguard Worker } 46*d9f75844SAndroid Build Coastguard Worker EvaluateHasExpired(TimeMs now)47*d9f75844SAndroid Build Coastguard Worker bool EvaluateHasExpired(TimeMs now) { 48*d9f75844SAndroid Build Coastguard Worker if (now >= expiry_) { 49*d9f75844SAndroid Build Coastguard Worker expiry_ = TimeMs::InfiniteFuture(); 50*d9f75844SAndroid Build Coastguard Worker return true; 51*d9f75844SAndroid Build Coastguard Worker } 52*d9f75844SAndroid Build Coastguard Worker return false; 53*d9f75844SAndroid Build Coastguard Worker } 54*d9f75844SAndroid Build Coastguard Worker timeout_id()55*d9f75844SAndroid Build Coastguard Worker TimeoutID timeout_id() const { return timeout_id_; } 56*d9f75844SAndroid Build Coastguard Worker 57*d9f75844SAndroid Build Coastguard Worker private: 58*d9f75844SAndroid Build Coastguard Worker const std::function<TimeMs()> get_time_; 59*d9f75844SAndroid Build Coastguard Worker const std::function<void(FakeTimeout*)> on_delete_; 60*d9f75844SAndroid Build Coastguard Worker 61*d9f75844SAndroid Build Coastguard Worker TimeoutID timeout_id_ = TimeoutID(0); 62*d9f75844SAndroid Build Coastguard Worker TimeMs expiry_ = TimeMs::InfiniteFuture(); 63*d9f75844SAndroid Build Coastguard Worker }; 64*d9f75844SAndroid Build Coastguard Worker 65*d9f75844SAndroid Build Coastguard Worker class FakeTimeoutManager { 66*d9f75844SAndroid Build Coastguard Worker public: 67*d9f75844SAndroid Build Coastguard Worker // The `get_time` function must return the current time, relative to any 68*d9f75844SAndroid Build Coastguard Worker // epoch. FakeTimeoutManager(std::function<TimeMs ()> get_time)69*d9f75844SAndroid Build Coastguard Worker explicit FakeTimeoutManager(std::function<TimeMs()> get_time) 70*d9f75844SAndroid Build Coastguard Worker : get_time_(std::move(get_time)) {} 71*d9f75844SAndroid Build Coastguard Worker CreateTimeout()72*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FakeTimeout> CreateTimeout() { 73*d9f75844SAndroid Build Coastguard Worker auto timer = std::make_unique<FakeTimeout>( 74*d9f75844SAndroid Build Coastguard Worker get_time_, [this](FakeTimeout* timer) { timers_.erase(timer); }); 75*d9f75844SAndroid Build Coastguard Worker timers_.insert(timer.get()); 76*d9f75844SAndroid Build Coastguard Worker return timer; 77*d9f75844SAndroid Build Coastguard Worker } CreateTimeout(webrtc::TaskQueueBase::DelayPrecision precision)78*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FakeTimeout> CreateTimeout( 79*d9f75844SAndroid Build Coastguard Worker webrtc::TaskQueueBase::DelayPrecision precision) { 80*d9f75844SAndroid Build Coastguard Worker // FakeTimeout does not support implement |precision|. 81*d9f75844SAndroid Build Coastguard Worker return CreateTimeout(); 82*d9f75844SAndroid Build Coastguard Worker } 83*d9f75844SAndroid Build Coastguard Worker 84*d9f75844SAndroid Build Coastguard Worker // NOTE: This can't return a vector, as calling EvaluateHasExpired requires 85*d9f75844SAndroid Build Coastguard Worker // calling socket->HandleTimeout directly afterwards, as the owning Timer 86*d9f75844SAndroid Build Coastguard Worker // still believes it's running, and it needs to be updated to set 87*d9f75844SAndroid Build Coastguard Worker // Timer::is_running_ to false before you operate on the Timer or Timeout 88*d9f75844SAndroid Build Coastguard Worker // again. GetNextExpiredTimeout()89*d9f75844SAndroid Build Coastguard Worker absl::optional<TimeoutID> GetNextExpiredTimeout() { 90*d9f75844SAndroid Build Coastguard Worker TimeMs now = get_time_(); 91*d9f75844SAndroid Build Coastguard Worker std::vector<TimeoutID> expired_timers; 92*d9f75844SAndroid Build Coastguard Worker for (auto& timer : timers_) { 93*d9f75844SAndroid Build Coastguard Worker if (timer->EvaluateHasExpired(now)) { 94*d9f75844SAndroid Build Coastguard Worker return timer->timeout_id(); 95*d9f75844SAndroid Build Coastguard Worker } 96*d9f75844SAndroid Build Coastguard Worker } 97*d9f75844SAndroid Build Coastguard Worker return absl::nullopt; 98*d9f75844SAndroid Build Coastguard Worker } 99*d9f75844SAndroid Build Coastguard Worker 100*d9f75844SAndroid Build Coastguard Worker private: 101*d9f75844SAndroid Build Coastguard Worker const std::function<TimeMs()> get_time_; 102*d9f75844SAndroid Build Coastguard Worker webrtc::flat_set<FakeTimeout*> timers_; 103*d9f75844SAndroid Build Coastguard Worker }; 104*d9f75844SAndroid Build Coastguard Worker 105*d9f75844SAndroid Build Coastguard Worker } // namespace dcsctp 106*d9f75844SAndroid Build Coastguard Worker 107*d9f75844SAndroid Build Coastguard Worker #endif // NET_DCSCTP_TIMER_FAKE_TIMEOUT_H_ 108