| // Copyright 2024 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef QUICHE_QUIC_CORE_QUIC_CONNECTION_ALARMS_H_ | |
| #define QUICHE_QUIC_CORE_QUIC_CONNECTION_ALARMS_H_ | |
| #include <array> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <optional> | |
| #include <string> | |
| #include "absl/base/nullability.h" | |
| #include "absl/types/variant.h" | |
| #include "quiche/quic/core/quic_alarm.h" | |
| #include "quiche/quic/core/quic_alarm_factory.h" | |
| #include "quiche/quic/core/quic_arena_scoped_ptr.h" | |
| #include "quiche/quic/core/quic_clock.h" | |
| #include "quiche/quic/core/quic_connection_context.h" | |
| #include "quiche/quic/core/quic_one_block_arena.h" | |
| #include "quiche/quic/core/quic_time.h" | |
| #include "quiche/common/platform/api/quiche_export.h" | |
| namespace quic { | |
| class QUICHE_EXPORT QuicConnectionAlarmsDelegate { | |
| public: | |
| virtual ~QuicConnectionAlarmsDelegate() = default; | |
| virtual void OnSendAlarm() = 0; | |
| virtual void OnAckAlarm() = 0; | |
| virtual void OnRetransmissionAlarm() = 0; | |
| virtual void OnMtuDiscoveryAlarm() = 0; | |
| virtual void OnProcessUndecryptablePacketsAlarm() = 0; | |
| virtual void OnDiscardPreviousOneRttKeysAlarm() = 0; | |
| virtual void OnDiscardZeroRttDecryptionKeysAlarm() = 0; | |
| virtual void MaybeProbeMultiPortPath() = 0; | |
| virtual void OnIdleDetectorAlarm() = 0; | |
| virtual void OnNetworkBlackholeDetectorAlarm() = 0; | |
| virtual void OnPingAlarm() = 0; | |
| virtual QuicConnectionContext* context() = 0; | |
| virtual const QuicClock* clock() const = 0; | |
| }; | |
| namespace test { | |
| class QuicAlarmMultiplexerPeer; | |
| class QuicConnectionAlarmsPeer; | |
| } // namespace test | |
| enum class QuicAlarmSlot : uint8_t { | |
| // An alarm that is scheduled when the SentPacketManager requires a delay | |
| // before sending packets and fires when the packet may be sent. | |
| kSend, | |
| // An alarm that fires when an ACK should be sent to the peer. | |
| kAck, | |
| // An alarm that fires when a packet needs to be retransmitted. | |
| kRetransmission, | |
| // An alarm that fires when an MTU probe should be sent. | |
| kMtuDiscovery, | |
| // An alarm that fires to process undecryptable packets when new decryption | |
| // keys are available. | |
| kProcessUndecryptablePackets, | |
| // An alarm that fires to discard keys for the previous key phase some time | |
| // after a key update has completed. | |
| kDiscardPreviousOneRttKeys, | |
| // An alarm that fires to discard 0-RTT decryption keys some time after the | |
| // first 1-RTT packet has been decrypted. Only used on server connections with | |
| // TLS handshaker. | |
| kDiscardZeroRttDecryptionKeys, | |
| // An alarm that fires to keep probing the multi-port path. | |
| kMultiPortProbing, | |
| // An alarm for QuicIdleNetworkDetector. | |
| kIdleNetworkDetector, | |
| // An alarm for QuicNetworkBlackholeDetection. | |
| kNetworkBlackholeDetector, | |
| // An alarm for QuicPingManager. | |
| kPing, | |
| // Must be the last element. | |
| kSlotCount | |
| }; | |
| std::string QuicAlarmSlotName(QuicAlarmSlot slot); | |
| // QuicAlarmMultiplexer manages the alarms used by the QuicConnection. Its main | |
| // purpose is to minimize the cost of scheduling and rescheduling the multiple | |
| // alarms that QuicConnection has by reducing all of those alarms to just two. | |
| class QUICHE_EXPORT QuicAlarmMultiplexer { | |
| public: | |
| // Proxy classes that allow an individual alarm to be accessed via | |
| // a QuicAlarm-compatible API. | |
| class AlarmProxy { | |
| public: | |
| AlarmProxy(QuicAlarmMultiplexer* multiplexer, QuicAlarmSlot slot) | |
| : multiplexer_(multiplexer), slot_(slot) {} | |
| bool IsSet() const { return multiplexer_->IsSet(slot_); } | |
| QuicTime deadline() const { return multiplexer_->GetDeadline(slot_); } | |
| bool IsPermanentlyCancelled() const { | |
| return multiplexer_->IsPermanentlyCancelled(); | |
| } | |
| void Set(QuicTime new_deadline) { multiplexer_->Set(slot_, new_deadline); } | |
| void Update(QuicTime new_deadline, QuicTime::Delta granularity) { | |
| multiplexer_->Update(slot_, new_deadline, granularity); | |
| } | |
| void Cancel() { multiplexer_->Cancel(slot_); } | |
| void PermanentCancel() {} | |
| private: | |
| friend class ::quic::test::QuicConnectionAlarmsPeer; | |
| QuicAlarmMultiplexer* multiplexer_; | |
| QuicAlarmSlot slot_; | |
| }; | |
| // Proxy classes that allow an individual alarm to be accessed via | |
| // a QuicAlarm-compatible API. | |
| class ConstAlarmProxy { | |
| public: | |
| ConstAlarmProxy(const QuicAlarmMultiplexer* multiplexer, QuicAlarmSlot slot) | |
| : multiplexer_(multiplexer), slot_(slot) {} | |
| bool IsSet() const { return multiplexer_->IsSet(slot_); } | |
| QuicTime deadline() const { return multiplexer_->GetDeadline(slot_); } | |
| bool IsPermanentlyCancelled() const { | |
| return multiplexer_->IsPermanentlyCancelled(); | |
| } | |
| private: | |
| const QuicAlarmMultiplexer* multiplexer_; | |
| QuicAlarmSlot slot_; | |
| }; | |
| static constexpr size_t kNumberOfSlots = | |
| static_cast<size_t>(QuicAlarmSlot::kSlotCount); | |
| QuicAlarmMultiplexer(absl::Nonnull<QuicConnectionAlarmsDelegate*> connection, | |
| QuicConnectionArena& arena, | |
| QuicAlarmFactory& alarm_factory); | |
| // QuicAlarmMultiplexer is not movable, as it has platform alarms that retain | |
| // a long-term pointer to it. | |
| QuicAlarmMultiplexer(const QuicAlarmMultiplexer&) = delete; | |
| QuicAlarmMultiplexer(QuicAlarmMultiplexer&&) = delete; | |
| QuicAlarmMultiplexer& operator=(const QuicAlarmMultiplexer&) = delete; | |
| QuicAlarmMultiplexer& operator=(QuicAlarmMultiplexer&&) = delete; | |
| // Implementation of QuicAlarm methods. | |
| void Set(QuicAlarmSlot slot, QuicTime new_deadline); | |
| void Update(QuicAlarmSlot slot, QuicTime new_deadline, | |
| QuicTimeDelta granularity); | |
| void Cancel(QuicAlarmSlot slot) { | |
| SetDeadlineFor(slot, QuicTime::Zero()); | |
| MaybeRescheduleUnderlyingAlarms(); | |
| } | |
| bool IsSet(QuicAlarmSlot slot) const { | |
| return GetDeadline(slot).IsInitialized(); | |
| } | |
| bool IsPermanentlyCancelled() const { return permanently_cancelled_; } | |
| QuicTime GetDeadline(QuicAlarmSlot slot) const { | |
| return deadlines_[static_cast<size_t>(slot)]; | |
| } | |
| void CancelAllAlarms(); | |
| // Executes callbacks for all of the alarms that are currently due. | |
| void FireAlarms(); | |
| // Methods used by ScopedPacketFlusher to defer updates to the underlying | |
| // platform alarm. | |
| void DeferUnderlyingAlarmScheduling(); | |
| void ResumeUnderlyingAlarmScheduling(); | |
| QuicConnectionAlarmsDelegate* delegate() { return connection_; } | |
| // Outputs a formatted list of active alarms. | |
| std::string DebugString(); | |
| private: | |
| friend class ::quic::test::QuicConnectionAlarmsPeer; | |
| friend class ::quic::test::QuicAlarmMultiplexerPeer; | |
| void SetDeadlineFor(QuicAlarmSlot slot, QuicTime deadline) { | |
| deadlines_[static_cast<size_t>(slot)] = deadline; | |
| } | |
| // Fires an individual alarm if it is set. | |
| void Fire(QuicAlarmSlot slot); | |
| void MaybeRescheduleUnderlyingAlarms() { | |
| if (defer_updates_of_underlying_alarms_ || permanently_cancelled_) { | |
| return; | |
| } | |
| RescheduleUnderlyingAlarms(); | |
| } | |
| // Updates the underlying platform alarm. | |
| void RescheduleUnderlyingAlarms(); | |
| // Deadlines for all of the alarms that can be placed into the multiplexer, | |
| // indexed by the values of QuicAlarmSlot enum. | |
| std::array<QuicTime, kNumberOfSlots> deadlines_; | |
| // Actual alarms provided by the underlying platform. Note that there are two | |
| // of them: the first is used for alarms that are scheduled for now or | |
| // earlier, and the latter is used for alarms that are scheduled in the | |
| // future. The reason those are split is that QUIC has a lot of alarms that | |
| // are only fired immediately, and splitting those allows to avoid having | |
| // extra reschedules. | |
| QuicArenaScopedPtr<QuicAlarm> now_alarm_; | |
| QuicArenaScopedPtr<QuicAlarm> later_alarm_; | |
| // Underlying connection and individual connection components. Not owned. | |
| QuicConnectionAlarmsDelegate* connection_; | |
| // Latched value of --quic_multiplexer_alarm_granularity_us. | |
| QuicTimeDelta underlying_alarm_granularity_; | |
| // If true, all of the alarms have been permanently cancelled. | |
| bool permanently_cancelled_ = false; | |
| // If true, the actual underlying alarms won't be rescheduled until | |
| // ResumeUnderlyingAlarmScheduling() is called. | |
| bool defer_updates_of_underlying_alarms_ = false; | |
| }; | |
| class QUICHE_EXPORT QuicConnectionAlarmHolder { | |
| public: | |
| // Provides a QuicAlarm-like interface to an alarm contained within | |
| // QuicConnectionAlarms. | |
| class AlarmProxy { | |
| public: | |
| explicit AlarmProxy(absl::Nonnull<QuicAlarm*> alarm) : alarm_(alarm) {} | |
| bool IsSet() const { return alarm_->IsSet(); } | |
| QuicTime deadline() const { return alarm_->deadline(); } | |
| bool IsPermanentlyCancelled() const { | |
| return alarm_->IsPermanentlyCancelled(); | |
| } | |
| void Set(QuicTime new_deadline) { alarm_->Set(new_deadline); } | |
| void Update(QuicTime new_deadline, QuicTime::Delta granularity) { | |
| alarm_->Update(new_deadline, granularity); | |
| } | |
| void Cancel() { alarm_->Cancel(); } | |
| void PermanentCancel() { alarm_->PermanentCancel(); } | |
| private: | |
| friend class ::quic::test::QuicConnectionAlarmsPeer; | |
| absl::Nonnull<QuicAlarm*> alarm_; | |
| }; | |
| // Provides a QuicAlarm-like interface to an alarm contained within | |
| // QuicConnectionAlarms. | |
| class ConstAlarmProxy { | |
| public: | |
| explicit ConstAlarmProxy(const QuicAlarm* alarm) : alarm_(alarm) {} | |
| bool IsSet() const { return alarm_->IsSet(); } | |
| QuicTime deadline() const { return alarm_->deadline(); } | |
| bool IsPermanentlyCancelled() const { | |
| return alarm_->IsPermanentlyCancelled(); | |
| } | |
| private: | |
| friend class ::quic::test::QuicConnectionAlarmsPeer; | |
| const QuicAlarm* alarm_; | |
| }; | |
| QuicConnectionAlarmHolder(QuicConnectionAlarmsDelegate* delegate, | |
| QuicAlarmFactory& alarm_factory, | |
| QuicConnectionArena& arena); | |
| AlarmProxy ack_alarm() { return AlarmProxy(ack_alarm_.get()); } | |
| AlarmProxy retransmission_alarm() { | |
| return AlarmProxy(retransmission_alarm_.get()); | |
| } | |
| AlarmProxy send_alarm() { return AlarmProxy(send_alarm_.get()); } | |
| AlarmProxy mtu_discovery_alarm() { | |
| return AlarmProxy(mtu_discovery_alarm_.get()); | |
| } | |
| AlarmProxy process_undecryptable_packets_alarm() { | |
| return AlarmProxy(process_undecryptable_packets_alarm_.get()); | |
| } | |
| AlarmProxy discard_previous_one_rtt_keys_alarm() { | |
| return AlarmProxy(discard_previous_one_rtt_keys_alarm_.get()); | |
| } | |
| AlarmProxy discard_zero_rtt_decryption_keys_alarm() { | |
| return AlarmProxy(discard_zero_rtt_decryption_keys_alarm_.get()); | |
| } | |
| AlarmProxy multi_port_probing_alarm() { | |
| return AlarmProxy(multi_port_probing_alarm_.get()); | |
| } | |
| AlarmProxy idle_network_detector_alarm() { | |
| return AlarmProxy(idle_network_detector_alarm_.get()); | |
| } | |
| AlarmProxy network_blackhole_detector_alarm() { | |
| return AlarmProxy(network_blackhole_detector_alarm_.get()); | |
| } | |
| AlarmProxy ping_alarm() { return AlarmProxy(ping_alarm_.get()); } | |
| ConstAlarmProxy ack_alarm() const { | |
| return ConstAlarmProxy(ack_alarm_.get()); | |
| } | |
| ConstAlarmProxy retransmission_alarm() const { | |
| return ConstAlarmProxy(retransmission_alarm_.get()); | |
| } | |
| ConstAlarmProxy send_alarm() const { | |
| return ConstAlarmProxy(send_alarm_.get()); | |
| } | |
| ConstAlarmProxy mtu_discovery_alarm() const { | |
| return ConstAlarmProxy(mtu_discovery_alarm_.get()); | |
| } | |
| ConstAlarmProxy process_undecryptable_packets_alarm() const { | |
| return ConstAlarmProxy(process_undecryptable_packets_alarm_.get()); | |
| } | |
| ConstAlarmProxy discard_previous_one_rtt_keys_alarm() const { | |
| return ConstAlarmProxy(discard_previous_one_rtt_keys_alarm_.get()); | |
| } | |
| ConstAlarmProxy discard_zero_rtt_decryption_keys_alarm() const { | |
| return ConstAlarmProxy(discard_zero_rtt_decryption_keys_alarm_.get()); | |
| } | |
| ConstAlarmProxy multi_port_probing_alarm() const { | |
| return ConstAlarmProxy(multi_port_probing_alarm_.get()); | |
| } | |
| ConstAlarmProxy idle_network_detector_alarm() const { | |
| return ConstAlarmProxy(idle_network_detector_alarm_.get()); | |
| } | |
| ConstAlarmProxy network_blackhole_detector_alarm() const { | |
| return ConstAlarmProxy(network_blackhole_detector_alarm_.get()); | |
| } | |
| ConstAlarmProxy ping_alarm() const { | |
| return ConstAlarmProxy(ping_alarm_.get()); | |
| } | |
| private: | |
| // An alarm that fires when an ACK should be sent to the peer. | |
| QuicArenaScopedPtr<QuicAlarm> ack_alarm_; | |
| // An alarm that fires when a packet needs to be retransmitted. | |
| QuicArenaScopedPtr<QuicAlarm> retransmission_alarm_; | |
| // An alarm that is scheduled when the SentPacketManager requires a delay | |
| // before sending packets and fires when the packet may be sent. | |
| QuicArenaScopedPtr<QuicAlarm> send_alarm_; | |
| // An alarm that fires when an MTU probe should be sent. | |
| QuicArenaScopedPtr<QuicAlarm> mtu_discovery_alarm_; | |
| // An alarm that fires to process undecryptable packets when new decryption | |
| // keys are available. | |
| QuicArenaScopedPtr<QuicAlarm> process_undecryptable_packets_alarm_; | |
| // An alarm that fires to discard keys for the previous key phase some time | |
| // after a key update has completed. | |
| QuicArenaScopedPtr<QuicAlarm> discard_previous_one_rtt_keys_alarm_; | |
| // An alarm that fires to discard 0-RTT decryption keys some time after the | |
| // first 1-RTT packet has been decrypted. Only used on server connections with | |
| // TLS handshaker. | |
| QuicArenaScopedPtr<QuicAlarm> discard_zero_rtt_decryption_keys_alarm_; | |
| // An alarm that fires to keep probing the multi-port path. | |
| QuicArenaScopedPtr<QuicAlarm> multi_port_probing_alarm_; | |
| // An alarm for QuicIdleNetworkDetector. | |
| QuicArenaScopedPtr<QuicAlarm> idle_network_detector_alarm_; | |
| // An alarm for QuicNetworkBlackholeDetection. | |
| QuicArenaScopedPtr<QuicAlarm> network_blackhole_detector_alarm_; | |
| // An alarm for QuicPingManager. | |
| QuicArenaScopedPtr<QuicAlarm> ping_alarm_; | |
| }; | |
| // A class for holding all QuicAlarms belonging to a single connection. | |
| // Dispatches all calls to either QuicConnectionAlarmHolder of | |
| // QuicAlarmMultiplexer. | |
| class QUICHE_EXPORT QuicConnectionAlarms { | |
| public: | |
| // Wraps a ConstAlarmProxy provided by either QuicConnectionAlarmHolder or | |
| // QuicAlarmMultiplexer. | |
| class ConstAlarmProxy { | |
| public: | |
| explicit ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy alarm) | |
| : alarm_(alarm) {} | |
| explicit ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy alarm) | |
| : alarm_(alarm) {} | |
| bool IsSet() const { | |
| return absl::visit([](auto& alarm) { return alarm.IsSet(); }, alarm_); | |
| } | |
| QuicTime deadline() const { | |
| return absl::visit([](auto& alarm) { return alarm.deadline(); }, alarm_); | |
| } | |
| bool IsPermanentlyCancelled() const { | |
| return absl::visit( | |
| [](auto& alarm) { return alarm.IsPermanentlyCancelled(); }, alarm_); | |
| } | |
| private: | |
| friend class ::quic::test::QuicConnectionAlarmsPeer; | |
| absl::variant<QuicConnectionAlarmHolder::ConstAlarmProxy, | |
| QuicAlarmMultiplexer::ConstAlarmProxy> | |
| alarm_; | |
| }; | |
| // Wraps an AlarmProxy provided by either QuicConnectionAlarmHolder or | |
| // QuicAlarmMultiplexer. | |
| class AlarmProxy { | |
| public: | |
| explicit AlarmProxy(QuicConnectionAlarmHolder::AlarmProxy alarm) | |
| : alarm_(alarm) {} | |
| explicit AlarmProxy(QuicAlarmMultiplexer::AlarmProxy alarm) | |
| : alarm_(alarm) {} | |
| bool IsSet() const { | |
| return absl::visit([](auto& alarm) { return alarm.IsSet(); }, alarm_); | |
| } | |
| QuicTime deadline() const { | |
| return absl::visit([](auto& alarm) { return alarm.deadline(); }, alarm_); | |
| } | |
| bool IsPermanentlyCancelled() const { | |
| return absl::visit( | |
| [](auto& alarm) { return alarm.IsPermanentlyCancelled(); }, alarm_); | |
| } | |
| void Set(QuicTime new_deadline) { | |
| absl::visit([&](auto& alarm) { alarm.Set(new_deadline); }, alarm_); | |
| } | |
| void Update(QuicTime new_deadline, QuicTime::Delta granularity) { | |
| absl::visit([&](auto& alarm) { alarm.Update(new_deadline, granularity); }, | |
| alarm_); | |
| } | |
| void Cancel() { | |
| absl::visit([&](auto& alarm) { alarm.Cancel(); }, alarm_); | |
| } | |
| void PermanentCancel() { | |
| absl::visit([&](auto& alarm) { alarm.PermanentCancel(); }, alarm_); | |
| } | |
| private: | |
| friend class ::quic::test::QuicConnectionAlarmsPeer; | |
| absl::variant<QuicConnectionAlarmHolder::AlarmProxy, | |
| QuicAlarmMultiplexer::AlarmProxy> | |
| alarm_; | |
| }; | |
| QuicConnectionAlarms(QuicConnectionAlarmsDelegate* delegate, | |
| QuicAlarmFactory& alarm_factory, | |
| QuicConnectionArena& arena); | |
| AlarmProxy ack_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy(&*multiplexer_, | |
| QuicAlarmSlot::kAck)); | |
| } | |
| return AlarmProxy( | |
| QuicConnectionAlarmHolder::AlarmProxy(holder_->ack_alarm())); | |
| } | |
| ConstAlarmProxy ack_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kAck)); | |
| } | |
| return ConstAlarmProxy( | |
| QuicConnectionAlarmHolder::ConstAlarmProxy(holder_->ack_alarm())); | |
| } | |
| AlarmProxy retransmission_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kRetransmission)); | |
| } | |
| return AlarmProxy( | |
| QuicConnectionAlarmHolder::AlarmProxy(holder_->retransmission_alarm())); | |
| } | |
| ConstAlarmProxy retransmission_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kRetransmission)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->retransmission_alarm())); | |
| } | |
| AlarmProxy send_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy(&*multiplexer_, | |
| QuicAlarmSlot::kSend)); | |
| } | |
| return AlarmProxy( | |
| QuicConnectionAlarmHolder::AlarmProxy(holder_->send_alarm())); | |
| } | |
| ConstAlarmProxy send_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kSend)); | |
| } | |
| return ConstAlarmProxy( | |
| QuicConnectionAlarmHolder::ConstAlarmProxy(holder_->send_alarm())); | |
| } | |
| AlarmProxy mtu_discovery_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kMtuDiscovery)); | |
| } | |
| return AlarmProxy( | |
| QuicConnectionAlarmHolder::AlarmProxy(holder_->mtu_discovery_alarm())); | |
| } | |
| ConstAlarmProxy mtu_discovery_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kMtuDiscovery)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->mtu_discovery_alarm())); | |
| } | |
| AlarmProxy process_undecryptable_packets_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kProcessUndecryptablePackets)); | |
| } | |
| return AlarmProxy(QuicConnectionAlarmHolder::AlarmProxy( | |
| holder_->process_undecryptable_packets_alarm())); | |
| } | |
| ConstAlarmProxy process_undecryptable_packets_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kProcessUndecryptablePackets)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->process_undecryptable_packets_alarm())); | |
| } | |
| AlarmProxy discard_previous_one_rtt_keys_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kDiscardPreviousOneRttKeys)); | |
| } | |
| return AlarmProxy(QuicConnectionAlarmHolder::AlarmProxy( | |
| holder_->discard_previous_one_rtt_keys_alarm())); | |
| } | |
| ConstAlarmProxy discard_previous_one_rtt_keys_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kDiscardPreviousOneRttKeys)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->discard_previous_one_rtt_keys_alarm())); | |
| } | |
| AlarmProxy discard_zero_rtt_decryption_keys_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kDiscardZeroRttDecryptionKeys)); | |
| } | |
| return AlarmProxy(QuicConnectionAlarmHolder::AlarmProxy( | |
| holder_->discard_zero_rtt_decryption_keys_alarm())); | |
| } | |
| ConstAlarmProxy discard_zero_rtt_decryption_keys_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kDiscardZeroRttDecryptionKeys)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->discard_zero_rtt_decryption_keys_alarm())); | |
| } | |
| AlarmProxy multi_port_probing_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kMultiPortProbing)); | |
| } | |
| return AlarmProxy(QuicConnectionAlarmHolder::AlarmProxy( | |
| holder_->multi_port_probing_alarm())); | |
| } | |
| ConstAlarmProxy multi_port_probing_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kMultiPortProbing)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->multi_port_probing_alarm())); | |
| } | |
| AlarmProxy idle_network_detector_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kIdleNetworkDetector)); | |
| } | |
| return AlarmProxy(QuicConnectionAlarmHolder::AlarmProxy( | |
| holder_->idle_network_detector_alarm())); | |
| } | |
| ConstAlarmProxy idle_network_detector_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kIdleNetworkDetector)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->idle_network_detector_alarm())); | |
| } | |
| AlarmProxy network_blackhole_detector_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kNetworkBlackholeDetector)); | |
| } | |
| return AlarmProxy(QuicConnectionAlarmHolder::AlarmProxy( | |
| holder_->network_blackhole_detector_alarm())); | |
| } | |
| ConstAlarmProxy network_blackhole_detector_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kNetworkBlackholeDetector)); | |
| } | |
| return ConstAlarmProxy(QuicConnectionAlarmHolder::ConstAlarmProxy( | |
| holder_->network_blackhole_detector_alarm())); | |
| } | |
| AlarmProxy ping_alarm() { | |
| if (use_multiplexer_) { | |
| return AlarmProxy(QuicAlarmMultiplexer::AlarmProxy(&*multiplexer_, | |
| QuicAlarmSlot::kPing)); | |
| } | |
| return AlarmProxy( | |
| QuicConnectionAlarmHolder::AlarmProxy(holder_->ping_alarm())); | |
| } | |
| ConstAlarmProxy ping_alarm() const { | |
| if (use_multiplexer_) { | |
| return ConstAlarmProxy(QuicAlarmMultiplexer::ConstAlarmProxy( | |
| &*multiplexer_, QuicAlarmSlot::kPing)); | |
| } | |
| return ConstAlarmProxy( | |
| QuicConnectionAlarmHolder::ConstAlarmProxy(holder_->ping_alarm())); | |
| } | |
| void CancelAllAlarms() { | |
| if (use_multiplexer_) { | |
| multiplexer_->CancelAllAlarms(); | |
| } | |
| } | |
| void DeferUnderlyingAlarmScheduling() { | |
| if (use_multiplexer_) { | |
| multiplexer_->DeferUnderlyingAlarmScheduling(); | |
| } | |
| } | |
| void ResumeUnderlyingAlarmScheduling() { | |
| if (use_multiplexer_) { | |
| multiplexer_->ResumeUnderlyingAlarmScheduling(); | |
| } | |
| } | |
| private: | |
| std::optional<QuicConnectionAlarmHolder> holder_; | |
| std::optional<QuicAlarmMultiplexer> multiplexer_; | |
| const bool use_multiplexer_; | |
| }; | |
| using QuicAlarmProxy = QuicConnectionAlarms::AlarmProxy; | |
| using QuicConstAlarmProxy = QuicConnectionAlarms::ConstAlarmProxy; | |
| } // namespace quic | |
| #endif // QUICHE_QUIC_CORE_QUIC_CONNECTION_ALARMS_H_ |