blob: a4f643ff6f3b1d02eccf65e9159c176e89650b08 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +00002/*
Davide Pesavento3b101d02018-07-21 22:44:09 -04003 * Copyright (c) 2013-2018 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080020 */
21
22#ifndef NDN_DETAIL_PENDING_INTEREST_HPP
23#define NDN_DETAIL_PENDING_INTEREST_HPP
24
Davide Pesavento3b101d02018-07-21 22:44:09 -040025#include "../face.hpp"
26
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080027#include "../data.hpp"
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000028#include "../interest.hpp"
Eric Newberry83872fd2015-08-06 17:01:24 -070029#include "../lp/nack.hpp"
Junxiao Shi103d8ed2016-08-07 20:34:10 +000030#include "../util/scheduler-scoped-event-id.hpp"
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080031
32namespace ndn {
33
Junxiao Shi103d8ed2016-08-07 20:34:10 +000034/**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000035 * @brief Indicates where a pending Interest came from
36 */
37enum class PendingInterestOrigin
38{
39 APP, ///< Interest was received from this app via Face::expressInterest API
40 FORWARDER ///< Interest was received from the forwarder via Transport
41};
42
43std::ostream&
44operator<<(std::ostream& os, PendingInterestOrigin origin)
45{
46 switch (origin) {
47 case PendingInterestOrigin::APP:
48 return os << "app";
49 case PendingInterestOrigin::FORWARDER:
50 return os << "forwarder";
51 }
52 BOOST_ASSERT(false);
53 return os;
54}
55
56/**
57 * @brief Stores a pending Interest and associated callbacks
Junxiao Shi103d8ed2016-08-07 20:34:10 +000058 */
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070059class PendingInterest : noncopyable
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070060{
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080061public:
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080062 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000063 * @brief Construct a pending Interest record for an Interest from Face::expressInterest
Junxiao Shi103d8ed2016-08-07 20:34:10 +000064 *
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000065 * The timeout is set based on the current time and InterestLifetime.
Junxiao Shi103d8ed2016-08-07 20:34:10 +000066 * This class will invoke the timeout callback unless the record is deleted before timeout.
67 *
68 * @param interest the Interest
69 * @param dataCallback invoked when matching Data packet is received
70 * @param nackCallback invoked when Nack matching Interest is received
71 * @param timeoutCallback invoked when Interest times out
72 * @param scheduler Scheduler for scheduling the timeout event
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080073 */
Eric Newberry83872fd2015-08-06 17:01:24 -070074 PendingInterest(shared_ptr<const Interest> interest,
75 const DataCallback& dataCallback,
76 const NackCallback& nackCallback,
77 const TimeoutCallback& timeoutCallback,
78 Scheduler& scheduler)
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000079 : m_interest(std::move(interest))
80 , m_origin(PendingInterestOrigin::APP)
Eric Newberry83872fd2015-08-06 17:01:24 -070081 , m_dataCallback(dataCallback)
82 , m_nackCallback(nackCallback)
83 , m_timeoutCallback(timeoutCallback)
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080084 , m_timeoutEvent(scheduler)
Junxiao Shi79a7a162017-09-09 08:33:57 +000085 , m_nNotNacked(0)
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080086 {
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000087 scheduleTimeoutEvent(scheduler);
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080088 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070089
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080090 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000091 * @brief Construct a pending Interest record for an Interest from NFD
92 *
93 * @param interest the Interest
94 * @param scheduler Scheduler for scheduling the timeout event
95 */
96 PendingInterest(shared_ptr<const Interest> interest, Scheduler& scheduler)
97 : m_interest(std::move(interest))
98 , m_origin(PendingInterestOrigin::FORWARDER)
99 , m_timeoutEvent(scheduler)
Junxiao Shi79a7a162017-09-09 08:33:57 +0000100 , m_nNotNacked(0)
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000101 {
102 scheduleTimeoutEvent(scheduler);
103 }
104
105 /**
106 * @brief Get the Interest
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800107 */
Eric Newberry83872fd2015-08-06 17:01:24 -0700108 shared_ptr<const Interest>
Alexander Afanasyev6fcdde22014-08-22 19:03:36 -0700109 getInterest() const
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800110 {
Eric Newberry83872fd2015-08-06 17:01:24 -0700111 return m_interest;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800112 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700113
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000114 PendingInterestOrigin
115 getOrigin() const
116 {
117 return m_origin;
118 }
119
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800120 /**
Junxiao Shi79a7a162017-09-09 08:33:57 +0000121 * @brief Record that the Interest has been forwarded to one destination
122 *
123 * A "destination" could be either a local InterestFilter or the forwarder.
124 */
125 void
126 recordForwarding()
127 {
128 ++m_nNotNacked;
129 }
130
131 /**
132 * @brief Record an incoming Nack against a forwarded Interest
133 * @return least severe Nack if all destinations where the Interest was forwarded have Nacked;
134 * otherwise, nullopt
135 */
136 optional<lp::Nack>
137 recordNack(const lp::Nack& nack)
138 {
139 --m_nNotNacked;
140 BOOST_ASSERT(m_nNotNacked >= 0);
141
142 if (!m_leastSevereNack || lp::isLessSevere(nack.getReason(), m_leastSevereNack->getReason())) {
143 m_leastSevereNack = nack;
144 }
145
146 return m_nNotNacked > 0 ? nullopt : m_leastSevereNack;
147 }
148
149 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000150 * @brief Invoke the Data callback
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000151 * @note This method does nothing if the Data callback is empty
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800152 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700153 void
Eric Newberry83872fd2015-08-06 17:01:24 -0700154 invokeDataCallback(const Data& data)
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800155 {
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000156 if (m_dataCallback != nullptr) {
157 m_dataCallback(*m_interest, data);
158 }
Eric Newberry83872fd2015-08-06 17:01:24 -0700159 }
160
161 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000162 * @brief Invoke the Nack callback
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000163 * @note This method does nothing if the Nack callback is empty
Eric Newberry83872fd2015-08-06 17:01:24 -0700164 */
165 void
166 invokeNackCallback(const lp::Nack& nack)
167 {
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000168 if (m_nackCallback != nullptr) {
169 m_nackCallback(*m_interest, nack);
170 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800171 }
172
173 /**
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000174 * @brief Set cleanup function to be invoked when Interest times out
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800175 */
176 void
177 setDeleter(const std::function<void()>& deleter)
178 {
179 m_deleter = deleter;
180 }
181
182private:
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000183 void
184 scheduleTimeoutEvent(Scheduler& scheduler)
185 {
186 m_timeoutEvent = scheduler.scheduleEvent(m_interest->getInterestLifetime(),
187 [=] { this->invokeTimeoutCallback(); });
188 }
189
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800190 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000191 * @brief Invoke the timeout callback (if non-empty) and the deleter
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800192 */
193 void
194 invokeTimeoutCallback()
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800195 {
Eric Newberry83872fd2015-08-06 17:01:24 -0700196 if (m_timeoutCallback) {
197 m_timeoutCallback(*m_interest);
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800198 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800199
200 BOOST_ASSERT(m_deleter);
201 m_deleter();
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800202 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700203
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800204private:
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700205 shared_ptr<const Interest> m_interest;
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000206 PendingInterestOrigin m_origin;
Eric Newberry83872fd2015-08-06 17:01:24 -0700207 DataCallback m_dataCallback;
208 NackCallback m_nackCallback;
209 TimeoutCallback m_timeoutCallback;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800210 util::scheduler::ScopedEventId m_timeoutEvent;
Junxiao Shi79a7a162017-09-09 08:33:57 +0000211 int m_nNotNacked; ///< number of Interest destinations that have not Nacked
212 optional<lp::Nack> m_leastSevereNack;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800213 std::function<void()> m_deleter;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800214};
215
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000216/**
217 * @brief Opaque type to identify a PendingInterest
218 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700219class PendingInterestId;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800220
221/**
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000222 * @brief Functor to match PendingInterestId
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800223 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700224class MatchPendingInterestId
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800225{
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700226public:
227 explicit
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700228 MatchPendingInterestId(const PendingInterestId* pendingInterestId)
229 : m_id(pendingInterestId)
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800230 {
231 }
232
233 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700234 operator()(const shared_ptr<const PendingInterest>& pendingInterest) const
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800235 {
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000236 return reinterpret_cast<const PendingInterestId*>(pendingInterest->getInterest().get()) == m_id;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800237 }
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000238
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800239private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700240 const PendingInterestId* m_id;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800241};
242
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800243} // namespace ndn
244
245#endif // NDN_DETAIL_PENDING_INTEREST_HPP