blob: ac14304e84cec282b9fb5b0c42f617c48eb6c983 [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/*
Junxiao Shi07115cc2019-01-23 19:00:59 +00003 * Copyright (c) 2013-2019 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
Junxiao Shi24c5a002018-12-12 04:47:15 +000022#ifndef NDN_IMPL_PENDING_INTEREST_HPP
23#define NDN_IMPL_PENDING_INTEREST_HPP
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080024
Davide Pesavento7e780642018-11-24 15:51:34 -050025#include "ndn-cxx/data.hpp"
26#include "ndn-cxx/face.hpp"
27#include "ndn-cxx/interest.hpp"
28#include "ndn-cxx/lp/nack.hpp"
Junxiao Shi07115cc2019-01-23 19:00:59 +000029#include "ndn-cxx/util/scheduler.hpp"
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080030
31namespace ndn {
32
Junxiao Shi103d8ed2016-08-07 20:34:10 +000033/**
Junxiao Shida9761f2019-02-11 15:05:33 -070034 * @brief Opaque type to identify a PendingInterest
35 */
36class PendingInterestId;
37
38/**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000039 * @brief Indicates where a pending Interest came from
40 */
41enum class PendingInterestOrigin
42{
43 APP, ///< Interest was received from this app via Face::expressInterest API
44 FORWARDER ///< Interest was received from the forwarder via Transport
45};
46
47std::ostream&
48operator<<(std::ostream& os, PendingInterestOrigin origin)
49{
50 switch (origin) {
51 case PendingInterestOrigin::APP:
52 return os << "app";
53 case PendingInterestOrigin::FORWARDER:
54 return os << "forwarder";
55 }
56 BOOST_ASSERT(false);
57 return os;
58}
59
60/**
61 * @brief Stores a pending Interest and associated callbacks
Junxiao Shi103d8ed2016-08-07 20:34:10 +000062 */
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070063class PendingInterest : noncopyable
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070064{
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080065public:
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080066 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000067 * @brief Construct a pending Interest record for an Interest from Face::expressInterest
Junxiao Shi103d8ed2016-08-07 20:34:10 +000068 *
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000069 * The timeout is set based on the current time and InterestLifetime.
Junxiao Shi103d8ed2016-08-07 20:34:10 +000070 * This class will invoke the timeout callback unless the record is deleted before timeout.
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080071 */
Junxiao Shida9761f2019-02-11 15:05:33 -070072 PendingInterest(const PendingInterestId* id,
73 shared_ptr<const Interest> interest,
Eric Newberry83872fd2015-08-06 17:01:24 -070074 const DataCallback& dataCallback,
75 const NackCallback& nackCallback,
76 const TimeoutCallback& timeoutCallback,
77 Scheduler& scheduler)
Junxiao Shida9761f2019-02-11 15:05:33 -070078 : m_id(id)
79 , m_interest(std::move(interest))
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000080 , m_origin(PendingInterestOrigin::APP)
Eric Newberry83872fd2015-08-06 17:01:24 -070081 , m_dataCallback(dataCallback)
82 , m_nackCallback(nackCallback)
83 , m_timeoutCallback(timeoutCallback)
Junxiao Shi79a7a162017-09-09 08:33:57 +000084 , m_nNotNacked(0)
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080085 {
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000086 scheduleTimeoutEvent(scheduler);
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080087 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070088
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080089 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000090 * @brief Construct a pending Interest record for an Interest from NFD
91 *
92 * @param interest the Interest
93 * @param scheduler Scheduler for scheduling the timeout event
94 */
95 PendingInterest(shared_ptr<const Interest> interest, Scheduler& scheduler)
Junxiao Shida9761f2019-02-11 15:05:33 -070096 : m_id(nullptr)
97 , m_interest(std::move(interest))
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000098 , m_origin(PendingInterestOrigin::FORWARDER)
Junxiao Shi79a7a162017-09-09 08:33:57 +000099 , m_nNotNacked(0)
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000100 {
101 scheduleTimeoutEvent(scheduler);
102 }
103
Junxiao Shida9761f2019-02-11 15:05:33 -0700104 const PendingInterestId*
105 getId() const
106 {
107 return m_id;
108 }
109
Eric Newberry83872fd2015-08-06 17:01:24 -0700110 shared_ptr<const Interest>
Alexander Afanasyev6fcdde22014-08-22 19:03:36 -0700111 getInterest() const
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800112 {
Eric Newberry83872fd2015-08-06 17:01:24 -0700113 return m_interest;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800114 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700115
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000116 PendingInterestOrigin
117 getOrigin() const
118 {
119 return m_origin;
120 }
121
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800122 /**
Junxiao Shi79a7a162017-09-09 08:33:57 +0000123 * @brief Record that the Interest has been forwarded to one destination
124 *
125 * A "destination" could be either a local InterestFilter or the forwarder.
126 */
127 void
128 recordForwarding()
129 {
130 ++m_nNotNacked;
131 }
132
133 /**
134 * @brief Record an incoming Nack against a forwarded Interest
135 * @return least severe Nack if all destinations where the Interest was forwarded have Nacked;
136 * otherwise, nullopt
137 */
138 optional<lp::Nack>
139 recordNack(const lp::Nack& nack)
140 {
141 --m_nNotNacked;
142 BOOST_ASSERT(m_nNotNacked >= 0);
143
144 if (!m_leastSevereNack || lp::isLessSevere(nack.getReason(), m_leastSevereNack->getReason())) {
145 m_leastSevereNack = nack;
146 }
147
148 return m_nNotNacked > 0 ? nullopt : m_leastSevereNack;
149 }
150
151 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000152 * @brief Invoke the Data callback
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000153 * @note This method does nothing if the Data callback is empty
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800154 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700155 void
Eric Newberry83872fd2015-08-06 17:01:24 -0700156 invokeDataCallback(const Data& data)
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800157 {
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000158 if (m_dataCallback != nullptr) {
159 m_dataCallback(*m_interest, data);
160 }
Eric Newberry83872fd2015-08-06 17:01:24 -0700161 }
162
163 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000164 * @brief Invoke the Nack callback
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000165 * @note This method does nothing if the Nack callback is empty
Eric Newberry83872fd2015-08-06 17:01:24 -0700166 */
167 void
168 invokeNackCallback(const lp::Nack& nack)
169 {
Junxiao Shi76e0eb22016-08-08 05:54:10 +0000170 if (m_nackCallback != nullptr) {
171 m_nackCallback(*m_interest, nack);
172 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800173 }
174
175 /**
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000176 * @brief Set cleanup function to be invoked when Interest times out
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800177 */
178 void
179 setDeleter(const std::function<void()>& deleter)
180 {
181 m_deleter = deleter;
182 }
183
184private:
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000185 void
186 scheduleTimeoutEvent(Scheduler& scheduler)
187 {
188 m_timeoutEvent = scheduler.scheduleEvent(m_interest->getInterestLifetime(),
189 [=] { this->invokeTimeoutCallback(); });
190 }
191
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800192 /**
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000193 * @brief Invoke the timeout callback (if non-empty) and the deleter
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800194 */
195 void
196 invokeTimeoutCallback()
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800197 {
Eric Newberry83872fd2015-08-06 17:01:24 -0700198 if (m_timeoutCallback) {
199 m_timeoutCallback(*m_interest);
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800200 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800201
202 BOOST_ASSERT(m_deleter);
203 m_deleter();
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800204 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700205
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800206private:
Junxiao Shida9761f2019-02-11 15:05:33 -0700207 const PendingInterestId* m_id;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700208 shared_ptr<const Interest> m_interest;
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000209 PendingInterestOrigin m_origin;
Eric Newberry83872fd2015-08-06 17:01:24 -0700210 DataCallback m_dataCallback;
211 NackCallback m_nackCallback;
212 TimeoutCallback m_timeoutCallback;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800213 util::scheduler::ScopedEventId m_timeoutEvent;
Junxiao Shi79a7a162017-09-09 08:33:57 +0000214 int m_nNotNacked; ///< number of Interest destinations that have not Nacked
215 optional<lp::Nack> m_leastSevereNack;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800216 std::function<void()> m_deleter;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800217};
218
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000219/**
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000220 * @brief Functor to match PendingInterestId
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800221 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700222class MatchPendingInterestId
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800223{
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700224public:
225 explicit
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700226 MatchPendingInterestId(const PendingInterestId* pendingInterestId)
227 : m_id(pendingInterestId)
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800228 {
229 }
230
231 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700232 operator()(const shared_ptr<const PendingInterest>& pendingInterest) const
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800233 {
Junxiao Shida9761f2019-02-11 15:05:33 -0700234 return pendingInterest->getId() == m_id;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800235 }
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000236
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800237private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700238 const PendingInterestId* m_id;
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800239};
240
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800241} // namespace ndn
242
Junxiao Shi24c5a002018-12-12 04:47:15 +0000243#endif // NDN_IMPL_PENDING_INTEREST_HPP