blob: fb216ca4d406c7f5a610b28bab2d1a536de42c35 [file] [log] [blame]
Jeff Thompson25b4e612013-10-10 16:03:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -07002/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07003 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -07005 * See COPYING for copyright and distribution information.
6 */
7
Jeff Thompsonea141d72013-09-19 14:40:10 -07008#include <stdexcept>
Alexander Afanasyevd409d592014-01-28 18:36:38 -08009#include "util/time.hpp"
Alexander Afanasyev96d914f2014-01-02 22:24:29 -080010
Yingdi Yu61ec2722014-01-20 14:22:32 -080011#include <ndn-cpp-dev/forwarding-entry.hpp>
12#include <ndn-cpp-dev/face-instance.hpp>
13#include <ndn-cpp-dev/node.hpp>
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070014
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080015#include "util/ndnd-id-fetcher.hpp"
Alexander Afanasyev96d914f2014-01-02 22:24:29 -080016
Yingdi Yu61ec2722014-01-20 14:22:32 -080017#include <ndn-cpp-dev/security/signature-sha256-with-rsa.hpp>
18#include <ndn-cpp-dev/status-response.hpp>
Alexander Afanasyev18371872014-01-05 23:00:26 -080019
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070020using namespace std;
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080021#if NDN_CPP_HAVE_CXX11
22// In the std library, the placeholders are in a different namespace than boost.
23using namespace ndn::func_lib::placeholders;
24#endif
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070025
26namespace ndn {
27
Alexander Afanasyev0b688dc2013-12-18 16:43:37 -080028Node::Node(const ptr_lib::shared_ptr<Transport>& transport)
Alexander Afanasyevbf082112014-01-09 14:27:55 -080029 : pitTimeoutCheckTimerActive_(false)
30 , transport_(transport)
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080031 , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
32{
33 ioService_ = ptr_lib::make_shared<boost::asio::io_service>();
34 pitTimeoutCheckTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
35 processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080036}
37
38Node::Node(const ptr_lib::shared_ptr<Transport>& transport, const ptr_lib::shared_ptr<boost::asio::io_service> &ioService)
39 : ioService_(ioService)
Alexander Afanasyevbf082112014-01-09 14:27:55 -080040 , pitTimeoutCheckTimerActive_(false)
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080041 , transport_(transport)
42 , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
Jeff Thompson557b81e2013-08-21 15:13:51 -070043{
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080044 pitTimeoutCheckTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
45 processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
Jeff Thompson557b81e2013-08-21 15:13:51 -070046}
47
Alexander Afanasyevb790d952014-01-24 12:07:53 -080048const PendingInterestId*
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080049Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070050{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080051 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080052 transport_->connect(*ioService_,
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -080053 ptr_lib::bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080054
Alexander Afanasyevb790d952014-01-24 12:07:53 -080055 ptr_lib::shared_ptr<const Interest> interestToExpress(new Interest(interest));
56
57 ioService_->post(func_lib::bind(&Node::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
58
59 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
60}
61
62void
63Node::asyncExpressInterest(const ptr_lib::shared_ptr<const Interest> &interest, const OnData& onData, const OnTimeout& onTimeout)
64{
65 pendingInterestTable_.push_back(ptr_lib::shared_ptr<PendingInterest>(new PendingInterest
66 (interest, onData, onTimeout)));
67
68 transport_->send(interest->wireEncode());
Alexander Afanasyevbf082112014-01-09 14:27:55 -080069
70 if (!pitTimeoutCheckTimerActive_) {
71 pitTimeoutCheckTimerActive_ = true;
72 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
73 pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
74 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070075}
Alexander Afanasyevb790d952014-01-24 12:07:53 -080076
Jeff Thompson11095142013-10-01 16:20:28 -070077void
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080078Node::put(const Data &data)
79{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080080 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080081 transport_->connect(*ioService_,
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -080082 ptr_lib::bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080083
84 transport_->send(data.wireEncode());
85}
86
87
88void
Alexander Afanasyevb790d952014-01-24 12:07:53 -080089Node::removePendingInterest(const PendingInterestId *pendingInterestId)
Jeff Thompson11095142013-10-01 16:20:28 -070090{
Alexander Afanasyevb790d952014-01-24 12:07:53 -080091 ioService_->post(func_lib::bind(&Node::asyncRemovePendingInterest, this, pendingInterestId));
Jeff Thompson11095142013-10-01 16:20:28 -070092}
93
Alexander Afanasyevb790d952014-01-24 12:07:53 -080094
95void
96Node::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
97{
98 std::remove_if(pendingInterestTable_.begin(), pendingInterestTable_.end(),
99 MatchPendingInterestId(pendingInterestId));
100}
101
102const RegisteredPrefixId*
Jeff Thompson590ec232013-09-18 15:55:56 -0700103Node::registerPrefix
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800104 (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700105{
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800106 ptr_lib::shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800107
Jeff Thompson86507bc2013-08-23 20:51:38 -0700108 if (ndndId_.size() == 0) {
109 // First fetch the ndndId of the connected hub.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800110 NdndIdFetcher fetcher(ndndId_,
111 func_lib::bind(&Node::registerPrefixHelper, this,
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800112 prefixToRegister, onRegisterFailed, flags),
113 func_lib::bind(onRegisterFailed, prefixToRegister->getPrefix().shared_from_this()));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800114
115 // @todo: Check if this crash
Jeff Thompsonce115762013-12-18 14:59:56 -0800116 // It is OK for func_lib::function make a copy of the function object because the Info is in a ptr_lib::shared_ptr.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800117 expressInterest(ndndIdFetcherInterest_, fetcher, fetcher);
Jeff Thompson86507bc2013-08-23 20:51:38 -0700118 }
119 else
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800120 registerPrefixHelper(prefixToRegister, onRegisterFailed, flags);
Jeff Thompson11095142013-10-01 16:20:28 -0700121
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800122 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
Jeff Thompson11095142013-10-01 16:20:28 -0700123}
124
125void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800126Node::removeRegisteredPrefix(const RegisteredPrefixId *registeredPrefixId)
Jeff Thompson11095142013-10-01 16:20:28 -0700127{
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800128 RegisteredPrefixTable::iterator i = std::find_if(registeredPrefixTable_.begin(), registeredPrefixTable_.end(),
129 MatchRegisteredPrefixId(registeredPrefixId));
130 if (i != registeredPrefixTable_.end())
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800131 {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800132 ForwardingEntry forwardingEntry("unreg", (*i)->getPrefix(), faceId_);
133 Data data;
134 data.setContent(forwardingEntry.wireEncode());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800135
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800136 SignatureSha256WithRsa signature;
137 signature.setValue(Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>()));
138 data.setSignature(signature);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800139
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800140 // Create an interest where the name has the encoded Data packet.
141 Name interestName;
142 interestName.append("ndnx");
143 interestName.append(ndndId_);
144 interestName.append("unreg");
145 interestName.append(data.wireEncode());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800146
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800147 Interest interest(interestName);
148 interest.setScope(1);
149 interest.setInterestLifetime(1000);
Alexander Afanasyevfb44c972014-01-26 11:38:07 -0800150 interest.setMustBeFresh(true);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800151
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800152 expressInterest(interest, OnData(), OnTimeout());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800153
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800154 registeredPrefixTable_.erase(i);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800155 }
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800156
157 // there cannot be two registered prefixes with the same id. if there are, then something is broken
Jeff Thompson86507bc2013-08-23 20:51:38 -0700158}
159
Jeff Thompson0050abe2013-09-17 12:50:25 -0700160void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800161Node::registerPrefixHelper(const ptr_lib::shared_ptr<RegisteredPrefix> &prefixToRegister,
Alexander Afanasyev79100492014-01-03 15:35:38 -0800162 const OnRegisterFailed& onRegisterFailed,
163 const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700164{
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700165 // Create a ForwardingEntry.
Alexander Afanasyevfbdfa092013-12-28 20:44:49 -0800166
167 // AlexA: ndnd ignores any freshness that is larger than 3600 sec and sets 300 sec instead
168 // to register "forever" (=2000000000 sec), freshnessPeriod must be omitted
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800169 ForwardingEntry forwardingEntry("selfreg", prefixToRegister->getPrefix(), -1, flags, -1);
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800170 Block content = forwardingEntry.wireEncode();
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700171
172 // Set the ForwardingEntry as the content of a Data packet and sign.
173 Data data;
Jeff Thompsonc2b7b142013-09-12 15:29:04 -0700174 data.setContent(content);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700175
Alexander Afanasyev79100492014-01-03 15:35:38 -0800176 // Create an empty signature, since nobody going to verify it for now
177 // @todo In the future, we may require real signatures to do the registration
178 SignatureSha256WithRsa signature;
179 signature.setValue(Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>()));
180 data.setSignature(signature);
181
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700182 // Create an interest where the name has the encoded Data packet.
183 Name interestName;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800184 interestName.append("ndnx");
Jeff Thompson3a715632013-10-31 11:36:35 -0700185 interestName.append(ndndId_);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800186 interestName.append("selfreg");
Alexander Afanasyev79100492014-01-03 15:35:38 -0800187 interestName.append(data.wireEncode());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800188
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700189 Interest interest(interestName);
190 interest.setScope(1);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800191 interest.setInterestLifetime(1000);
Alexander Afanasyevfb44c972014-01-26 11:38:07 -0800192 interest.setMustBeFresh(true);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800193
194 expressInterest(interest,
195 func_lib::bind(&Node::registerPrefixFinal, this,
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800196 prefixToRegister, onRegisterFailed, _1, _2),
197 func_lib::bind(onRegisterFailed, prefixToRegister->getPrefix().shared_from_this()));
Alexander Afanasyev18371872014-01-05 23:00:26 -0800198}
199
200void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800201Node::registerPrefixFinal(const ptr_lib::shared_ptr<RegisteredPrefix> &prefixToRegister,
Alexander Afanasyev18371872014-01-05 23:00:26 -0800202 const OnRegisterFailed& onRegisterFailed,
203 const ptr_lib::shared_ptr<const Interest>&, const ptr_lib::shared_ptr<Data>&data)
204{
205 Block content = data->getContent();
206 content.parse();
207
208 if (content.getAll().empty())
209 {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800210 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800211 return;
212 }
213
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800214 Block::element_iterator val = content.getAll().begin();
215
216 switch(val->type())
Alexander Afanasyev18371872014-01-05 23:00:26 -0800217 {
218 case Tlv::FaceManagement::ForwardingEntry:
219 {
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800220 ForwardingEntry entry;
221 entry.wireDecode(*val);
222
223 // Save the onInterest callback and send the registration interest.
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800224 registeredPrefixTable_.push_back(prefixToRegister);
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800225
226 /// @todo Notify user about successful registration
227
Alexander Afanasyev18371872014-01-05 23:00:26 -0800228 // succeeded
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800229 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800230 }
231 case Tlv::FaceManagement::StatusResponse:
232 {
233 // failed :(
234 StatusResponse resp;
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800235 resp.wireDecode(*val);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800236
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800237 // std::cerr << "StatusReponse: " << resp << std::endl;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800238
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800239 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800240 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800241 }
242 default:
243 {
244 // failed :(
245
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800246 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800247 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800248 }
249 }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700250}
251
Jeff Thompson0050abe2013-09-17 12:50:25 -0700252void
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800253Node::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700254{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800255 try
256 {
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800257 if (timeout < 0)
258 {
259 // do not block if timeout is negative, but process pending events
260 ioService_->poll();
261 return;
262 }
263
264 if (timeout > 0)
265 {
266 processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
Jeff Thompson6e9fc182014-01-23 13:04:08 -0800267 processEventsTimeoutTimer_->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800268 }
269
270 if (keepThread) {
271 // work will ensure that ioService_ is running until work object exists
272 ioServiceWork_ = ptr_lib::make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
273 }
274
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -0800275 ioService_->run();
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800276 ioService_->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800277 }
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800278 catch(Node::ProcessEventsTimeout &)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800279 {
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800280 // break
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800281 ioService_->reset();
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800282 }
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800283 catch(const std::exception &)
284 {
285 ioService_->reset();
286 pendingInterestTable_.clear();
287 registeredPrefixTable_.clear();
288 throw;
289 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800290}
291
292void
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800293Node::fireProcessEventsTimeout(const boost::system::error_code& error)
294{
295 if (!error) // can fire for some other reason, e.g., cancelled
296 throw Node::ProcessEventsTimeout();
297}
298
299void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800300Node::checkPitExpire()
301{
Jeff Thompson48917f02013-08-21 17:12:45 -0700302 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700303 MillisecondsSince1970 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson11095142013-10-01 16:20:28 -0700304 for (int i = (int)pendingInterestTable_.size() - 1; i >= 0; --i) {
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800305 if (pendingInterestTable_[i]->isTimedOut(nowMilliseconds)) {
306 // Save the PendingInterest and remove it from the PIT. Then call the callback.
Jeff Thompsonce115762013-12-18 14:59:56 -0800307 ptr_lib::shared_ptr<PendingInterest> pendingInterest = pendingInterestTable_[i];
Jeff Thompson11095142013-10-01 16:20:28 -0700308 pendingInterestTable_.erase(pendingInterestTable_.begin() + i);
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800309 pendingInterest->callTimeout();
Jeff Thompson48917f02013-08-21 17:12:45 -0700310
311 // Refresh now since the timeout callback might have delayed.
Jeff Thompson9ae4d782013-10-17 10:25:54 -0700312 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson48917f02013-08-21 17:12:45 -0700313 }
314 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800315
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800316 if (!pendingInterestTable_.empty()) {
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800317 pitTimeoutCheckTimerActive_ = true;
318
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800319 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
320 pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
321 }
322 else {
323 pitTimeoutCheckTimerActive_ = false;
324
325 if (registeredPrefixTable_.empty()) {
326 transport_->close();
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800327 if (!ioServiceWork_) {
328 processEventsTimeoutTimer_->cancel();
329 }
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800330 }
331 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700332}
333
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800334
Jeff Thompson0050abe2013-09-17 12:50:25 -0700335void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800336Node::onReceiveElement(const Block &block)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700337{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800338 if (block.type() == Tlv::Interest)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800339 {
340 ptr_lib::shared_ptr<Interest> interest(new Interest());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800341 interest->wireDecode(block);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700342
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800343 RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
344 if (entry != registeredPrefixTable_.end()) {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800345 (*entry)->getOnInterest()((*entry)->getPrefix().shared_from_this(), interest);
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800346 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700347 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800348 else if (block.type() == Tlv::Data)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800349 {
350 ptr_lib::shared_ptr<Data> data(new Data());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800351 data->wireDecode(block);
352
353 PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
354 if (entry != pendingInterestTable_.end()) {
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800355 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800356 const OnData onData = (*entry)->getOnData();
357 const ptr_lib::shared_ptr<const Interest> interest = (*entry)->getInterest();
358 pendingInterestTable_.erase(entry);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800359
360 if (onData) {
361 onData(interest, data);
362 }
363
364 if (pendingInterestTable_.empty()) {
365 pitTimeoutCheckTimer_->cancel(); // this will cause checkPitExpire invocation
366 }
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800367 }
368 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700369}
370
Jeff Thompson0050abe2013-09-17 12:50:25 -0700371void
372Node::shutdown()
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700373{
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800374 pendingInterestTable_.clear();
375 registeredPrefixTable_.clear();
376
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700377 transport_->close();
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800378 pitTimeoutCheckTimer_->cancel();
379 processEventsTimeoutTimer_->cancel();
380 pitTimeoutCheckTimerActive_ = false;
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700381}
382
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800383Node::PendingInterestTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700384Node::getEntryIndexForExpressedInterest(const Name& name)
Jeff Thompson557b81e2013-08-21 15:13:51 -0700385{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800386 for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
387 i != pendingInterestTable_.end(); ++i)
388 {
389 if ((*i)->getInterest()->matchesName(name))
390 {
391 return i;
392 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700393 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800394
395 return pendingInterestTable_.end();
Jeff Thompson557b81e2013-08-21 15:13:51 -0700396}
Jeff Thompson86507bc2013-08-23 20:51:38 -0700397
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800398Node::RegisteredPrefixTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700399Node::getEntryForRegisteredPrefix(const Name& name)
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700400{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800401 RegisteredPrefixTable::iterator longestPrefix = registeredPrefixTable_.end();
402
403 for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
404 i != registeredPrefixTable_.end();
405 ++i)
406 {
407 if (longestPrefix == registeredPrefixTable_.end() ||
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800408 (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800409 {
410 longestPrefix = i;
411 }
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700412 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800413 return longestPrefix;
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700414}
415
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800416Node::PendingInterest::PendingInterest(const ptr_lib::shared_ptr<const Interest>& interest,
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800417 const OnData& onData, const OnTimeout& onTimeout)
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800418: interest_(interest),
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800419 onData_(onData), onTimeout_(onTimeout)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700420{
421 // Set up timeoutTime_.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800422 if (interest_->getInterestLifetime() >= 0)
423 timeoutTimeMilliseconds_ = ndn_getNowMilliseconds() + interest_->getInterestLifetime();
Jeff Thompson86507bc2013-08-23 20:51:38 -0700424 else
425 // No timeout.
Alexander Afanasyevb24a68a2013-12-28 16:53:21 -0800426 /**
427 * @todo Set more meaningful default timeout. This timeout MUST exist.
428 */
429 timeoutTimeMilliseconds_ = ndn_getNowMilliseconds() + 4000;
Jeff Thompson86507bc2013-08-23 20:51:38 -0700430}
431
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800432void
433Node::PendingInterest::callTimeout()
Jeff Thompson86507bc2013-08-23 20:51:38 -0700434{
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800435 if (onTimeout_) {
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800436 onTimeout_(interest_);
Jeff Thompson86507bc2013-08-23 20:51:38 -0700437 }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700438}
Jeff Thompson557b81e2013-08-21 15:13:51 -0700439
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700440}