blob: e0e90a06cab5da424ad0088ada00c7da1739441a [file] [log] [blame]
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstddef>
#include <cstdint>
#include <lib/core/Optional.h>
#include <lib/core/PeerId.h>
#include <system/SystemClock.h>
namespace mdns {
namespace Minimal {
/// Keeps track of active resolve attempts
///
/// Maintains a list of 'pending mdns resolve queries' and provides operations
/// for:
/// - add/remove to the list
/// - figuring out a 'next query time' for items in the list
/// - iterating through the 'schedule now' items of the list
///
class ActiveResolveAttempts
{
public:
static constexpr size_t kRetryQueueSize = 4;
static constexpr chip::System::Clock::Timeout kMaxRetryDelay = chip::System::Clock::Seconds16(16);
ActiveResolveAttempts(chip::System::Clock::ClockBase * clock) : mClock(clock) { Reset(); }
/// Clear out the internal queue
void Reset();
/// Mark a resolution as a success, removing it from the internal list
void Complete(const chip::PeerId & peerId);
/// Mark that a resolution is pending, adding it to the internal list
///
/// Once this complete, this peer id will be returned immediately
/// by NextScheduledPeer (potentially with others as well)
void MarkPending(const chip::PeerId & peerId);
// Get minimum time until the next pending reply is required.
//
// Returns missing if no actively tracked elements exist.
chip::Optional<chip::System::Clock::Timeout> GetTimeUntilNextExpectedResponse() const;
// Get the peer Id that needs scheduling for a query
//
// Assumes that the resolution is being sent and will apply internal
// query logic. This means:
// - internal tracking of 'next due time' will updated as 'request sent
// now'
// - there is NO sorting implied by this call. Returned value will be
// any peer that needs a new request sent
chip::Optional<chip::PeerId> NextScheduledPeer();
private:
struct RetryEntry
{
// What peer id is pending resolution.
//
// Inactive entries are marked by having NodeId == kUndefinedNodeId
chip::PeerId peerId;
// When a reply is expected for this item
chip::System::Clock::Timestamp queryDueTime;
// Next expected delay for sending if reply is not reached by
// 'queryDueTimeMs'
//
// Based on RFC 6762 expectations are:
// - the interval between the first two queries MUST be at least
// one second
// - the intervals between successive queries MUST increase by at
// least a factor of two
chip::System::Clock::Timeout nextRetryDelay = chip::System::Clock::Seconds16(1);
};
chip::System::Clock::ClockBase * mClock;
RetryEntry mRetryQueue[kRetryQueueSize];
};
} // namespace Minimal
} // namespace mdns