blob: 0c9c8725e20af79bde0e02aad10fff2883fb822d [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
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -08008#include "common.hpp"
9
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -080010#include "node.hpp"
Alexander Afanasyev96d914f2014-01-02 22:24:29 -080011
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080012#include "forwarding-entry.hpp"
13#include "face-instance.hpp"
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080014#include "status-response.hpp"
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -080015#include "security/signature-sha256-with-rsa.hpp"
16
17#include "util/time.hpp"
18#include "util/random.hpp"
19#include "util/ndnd-id-fetcher.hpp"
Alexander Afanasyev18371872014-01-05 23:00:26 -080020
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070021using namespace std;
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080022#if NDN_CPP_HAVE_CXX11
23// In the std library, the placeholders are in a different namespace than boost.
24using namespace ndn::func_lib::placeholders;
25#endif
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070026
27namespace ndn {
28
Alexander Afanasyev0b688dc2013-12-18 16:43:37 -080029Node::Node(const ptr_lib::shared_ptr<Transport>& transport)
Alexander Afanasyevbf082112014-01-09 14:27:55 -080030 : pitTimeoutCheckTimerActive_(false)
31 , transport_(transport)
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080032 , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
33{
34 ioService_ = ptr_lib::make_shared<boost::asio::io_service>();
35 pitTimeoutCheckTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
36 processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080037}
38
39Node::Node(const ptr_lib::shared_ptr<Transport>& transport, const ptr_lib::shared_ptr<boost::asio::io_service> &ioService)
40 : ioService_(ioService)
Alexander Afanasyevbf082112014-01-09 14:27:55 -080041 , pitTimeoutCheckTimerActive_(false)
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080042 , transport_(transport)
43 , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
Jeff Thompson557b81e2013-08-21 15:13:51 -070044{
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080045 pitTimeoutCheckTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
46 processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
Jeff Thompson557b81e2013-08-21 15:13:51 -070047}
48
Alexander Afanasyevb790d952014-01-24 12:07:53 -080049const PendingInterestId*
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080050Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070051{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080052 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080053 transport_->connect(*ioService_,
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -080054 ptr_lib::bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080055
Alexander Afanasyevb790d952014-01-24 12:07:53 -080056 ptr_lib::shared_ptr<const Interest> interestToExpress(new Interest(interest));
57
58 ioService_->post(func_lib::bind(&Node::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
59
60 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
61}
62
63void
64Node::asyncExpressInterest(const ptr_lib::shared_ptr<const Interest> &interest, const OnData& onData, const OnTimeout& onTimeout)
65{
66 pendingInterestTable_.push_back(ptr_lib::shared_ptr<PendingInterest>(new PendingInterest
67 (interest, onData, onTimeout)));
68
69 transport_->send(interest->wireEncode());
Alexander Afanasyevbf082112014-01-09 14:27:55 -080070
71 if (!pitTimeoutCheckTimerActive_) {
72 pitTimeoutCheckTimerActive_ = true;
73 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
74 pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
75 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070076}
Alexander Afanasyevb790d952014-01-24 12:07:53 -080077
Jeff Thompson11095142013-10-01 16:20:28 -070078void
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080079Node::put(const Data &data)
80{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080081 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080082 transport_->connect(*ioService_,
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -080083 ptr_lib::bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080084
85 transport_->send(data.wireEncode());
86}
87
88
89void
Alexander Afanasyevb790d952014-01-24 12:07:53 -080090Node::removePendingInterest(const PendingInterestId *pendingInterestId)
Jeff Thompson11095142013-10-01 16:20:28 -070091{
Alexander Afanasyevb790d952014-01-24 12:07:53 -080092 ioService_->post(func_lib::bind(&Node::asyncRemovePendingInterest, this, pendingInterestId));
Jeff Thompson11095142013-10-01 16:20:28 -070093}
94
Alexander Afanasyevb790d952014-01-24 12:07:53 -080095
96void
97Node::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
98{
99 std::remove_if(pendingInterestTable_.begin(), pendingInterestTable_.end(),
100 MatchPendingInterestId(pendingInterestId));
101}
102
103const RegisteredPrefixId*
Jeff Thompson590ec232013-09-18 15:55:56 -0700104Node::registerPrefix
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800105 (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700106{
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800107 ptr_lib::shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800108
Jeff Thompson86507bc2013-08-23 20:51:38 -0700109 if (ndndId_.size() == 0) {
110 // First fetch the ndndId of the connected hub.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800111 NdndIdFetcher fetcher(ndndId_,
112 func_lib::bind(&Node::registerPrefixHelper, this,
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800113 prefixToRegister, onRegisterFailed, flags),
114 func_lib::bind(onRegisterFailed, prefixToRegister->getPrefix().shared_from_this()));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800115
116 // @todo: Check if this crash
Jeff Thompsonce115762013-12-18 14:59:56 -0800117 // 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 -0800118 expressInterest(ndndIdFetcherInterest_, fetcher, fetcher);
Jeff Thompson86507bc2013-08-23 20:51:38 -0700119 }
120 else
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800121 registerPrefixHelper(prefixToRegister, onRegisterFailed, flags);
Jeff Thompson11095142013-10-01 16:20:28 -0700122
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800123 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
Jeff Thompson11095142013-10-01 16:20:28 -0700124}
125
126void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800127Node::removeRegisteredPrefix(const RegisteredPrefixId *registeredPrefixId)
Jeff Thompson11095142013-10-01 16:20:28 -0700128{
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800129 RegisteredPrefixTable::iterator i = std::find_if(registeredPrefixTable_.begin(), registeredPrefixTable_.end(),
130 MatchRegisteredPrefixId(registeredPrefixId));
131 if (i != registeredPrefixTable_.end())
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800132 {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800133 ForwardingEntry forwardingEntry("unreg", (*i)->getPrefix(), faceId_);
134 Data data;
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -0800135 // This ensures uniqueness of each prefix registration commands
136 data.setName(Name().appendVersion(random::generateWord32()));
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800137 data.setContent(forwardingEntry.wireEncode());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800138
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800139 SignatureSha256WithRsa signature;
140 signature.setValue(Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>()));
141 data.setSignature(signature);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800142
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800143 // Create an interest where the name has the encoded Data packet.
144 Name interestName;
145 interestName.append("ndnx");
146 interestName.append(ndndId_);
147 interestName.append("unreg");
148 interestName.append(data.wireEncode());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800149
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800150 Interest interest(interestName);
151 interest.setScope(1);
152 interest.setInterestLifetime(1000);
Alexander Afanasyevfb44c972014-01-26 11:38:07 -0800153 interest.setMustBeFresh(true);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800154
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800155 expressInterest(interest, OnData(), OnTimeout());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800156
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800157 registeredPrefixTable_.erase(i);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800158 }
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800159
160 // there cannot be two registered prefixes with the same id. if there are, then something is broken
Jeff Thompson86507bc2013-08-23 20:51:38 -0700161}
162
Jeff Thompson0050abe2013-09-17 12:50:25 -0700163void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800164Node::registerPrefixHelper(const ptr_lib::shared_ptr<RegisteredPrefix> &prefixToRegister,
Alexander Afanasyev79100492014-01-03 15:35:38 -0800165 const OnRegisterFailed& onRegisterFailed,
166 const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700167{
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700168 // Create a ForwardingEntry.
Alexander Afanasyevfbdfa092013-12-28 20:44:49 -0800169
170 // AlexA: ndnd ignores any freshness that is larger than 3600 sec and sets 300 sec instead
171 // to register "forever" (=2000000000 sec), freshnessPeriod must be omitted
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800172 ForwardingEntry forwardingEntry("selfreg", prefixToRegister->getPrefix(), -1, flags, -1);
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800173 Block content = forwardingEntry.wireEncode();
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700174
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -0800175
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700176 // Set the ForwardingEntry as the content of a Data packet and sign.
177 Data data;
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -0800178 // This ensures uniqueness of each prefix registration commands
179 data.setName(Name().appendVersion(random::generateWord32()));
Jeff Thompsonc2b7b142013-09-12 15:29:04 -0700180 data.setContent(content);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700181
Alexander Afanasyev79100492014-01-03 15:35:38 -0800182 // Create an empty signature, since nobody going to verify it for now
183 // @todo In the future, we may require real signatures to do the registration
184 SignatureSha256WithRsa signature;
185 signature.setValue(Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>()));
186 data.setSignature(signature);
187
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700188 // Create an interest where the name has the encoded Data packet.
189 Name interestName;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800190 interestName.append("ndnx");
Jeff Thompson3a715632013-10-31 11:36:35 -0700191 interestName.append(ndndId_);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800192 interestName.append("selfreg");
Alexander Afanasyev79100492014-01-03 15:35:38 -0800193 interestName.append(data.wireEncode());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800194
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700195 Interest interest(interestName);
196 interest.setScope(1);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800197 interest.setInterestLifetime(1000);
Alexander Afanasyevfb44c972014-01-26 11:38:07 -0800198 interest.setMustBeFresh(true);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800199
200 expressInterest(interest,
201 func_lib::bind(&Node::registerPrefixFinal, this,
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800202 prefixToRegister, onRegisterFailed, _1, _2),
203 func_lib::bind(onRegisterFailed, prefixToRegister->getPrefix().shared_from_this()));
Alexander Afanasyev18371872014-01-05 23:00:26 -0800204}
205
206void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800207Node::registerPrefixFinal(const ptr_lib::shared_ptr<RegisteredPrefix> &prefixToRegister,
Alexander Afanasyev18371872014-01-05 23:00:26 -0800208 const OnRegisterFailed& onRegisterFailed,
209 const ptr_lib::shared_ptr<const Interest>&, const ptr_lib::shared_ptr<Data>&data)
210{
211 Block content = data->getContent();
212 content.parse();
213
214 if (content.getAll().empty())
215 {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800216 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800217 return;
218 }
219
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800220 Block::element_iterator val = content.getAll().begin();
221
222 switch(val->type())
Alexander Afanasyev18371872014-01-05 23:00:26 -0800223 {
224 case Tlv::FaceManagement::ForwardingEntry:
225 {
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800226 ForwardingEntry entry;
227 entry.wireDecode(*val);
228
229 // Save the onInterest callback and send the registration interest.
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800230 registeredPrefixTable_.push_back(prefixToRegister);
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800231
232 /// @todo Notify user about successful registration
233
Alexander Afanasyev18371872014-01-05 23:00:26 -0800234 // succeeded
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800235 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800236 }
237 case Tlv::FaceManagement::StatusResponse:
238 {
239 // failed :(
240 StatusResponse resp;
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800241 resp.wireDecode(*val);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800242
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800243 // std::cerr << "StatusReponse: " << resp << std::endl;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800244
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800245 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800246 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800247 }
248 default:
249 {
250 // failed :(
251
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800252 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800253 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800254 }
255 }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700256}
257
Jeff Thompson0050abe2013-09-17 12:50:25 -0700258void
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800259Node::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700260{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800261 try
262 {
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800263 if (timeout < 0)
264 {
265 // do not block if timeout is negative, but process pending events
266 ioService_->poll();
267 return;
268 }
269
270 if (timeout > 0)
271 {
272 processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
Jeff Thompson6e9fc182014-01-23 13:04:08 -0800273 processEventsTimeoutTimer_->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800274 }
275
276 if (keepThread) {
277 // work will ensure that ioService_ is running until work object exists
278 ioServiceWork_ = ptr_lib::make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
279 }
280
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -0800281 ioService_->run();
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800282 ioService_->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800283 }
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800284 catch(Node::ProcessEventsTimeout &)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800285 {
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800286 // break
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800287 ioService_->reset();
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800288 }
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800289 catch(const std::exception &)
290 {
291 ioService_->reset();
292 pendingInterestTable_.clear();
293 registeredPrefixTable_.clear();
294 throw;
295 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800296}
297
298void
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800299Node::fireProcessEventsTimeout(const boost::system::error_code& error)
300{
301 if (!error) // can fire for some other reason, e.g., cancelled
302 throw Node::ProcessEventsTimeout();
303}
304
305void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800306Node::checkPitExpire()
307{
Jeff Thompson48917f02013-08-21 17:12:45 -0700308 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700309 MillisecondsSince1970 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson11095142013-10-01 16:20:28 -0700310 for (int i = (int)pendingInterestTable_.size() - 1; i >= 0; --i) {
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800311 if (pendingInterestTable_[i]->isTimedOut(nowMilliseconds)) {
312 // Save the PendingInterest and remove it from the PIT. Then call the callback.
Jeff Thompsonce115762013-12-18 14:59:56 -0800313 ptr_lib::shared_ptr<PendingInterest> pendingInterest = pendingInterestTable_[i];
Jeff Thompson11095142013-10-01 16:20:28 -0700314 pendingInterestTable_.erase(pendingInterestTable_.begin() + i);
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800315 pendingInterest->callTimeout();
Jeff Thompson48917f02013-08-21 17:12:45 -0700316
317 // Refresh now since the timeout callback might have delayed.
Jeff Thompson9ae4d782013-10-17 10:25:54 -0700318 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson48917f02013-08-21 17:12:45 -0700319 }
320 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800321
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800322 if (!pendingInterestTable_.empty()) {
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800323 pitTimeoutCheckTimerActive_ = true;
324
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800325 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
326 pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
327 }
328 else {
329 pitTimeoutCheckTimerActive_ = false;
330
331 if (registeredPrefixTable_.empty()) {
332 transport_->close();
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800333 if (!ioServiceWork_) {
334 processEventsTimeoutTimer_->cancel();
335 }
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800336 }
337 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700338}
339
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800340
Jeff Thompson0050abe2013-09-17 12:50:25 -0700341void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800342Node::onReceiveElement(const Block &block)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700343{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800344 if (block.type() == Tlv::Interest)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800345 {
346 ptr_lib::shared_ptr<Interest> interest(new Interest());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800347 interest->wireDecode(block);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700348
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800349 RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
350 if (entry != registeredPrefixTable_.end()) {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800351 (*entry)->getOnInterest()((*entry)->getPrefix().shared_from_this(), interest);
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800352 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700353 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800354 else if (block.type() == Tlv::Data)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800355 {
356 ptr_lib::shared_ptr<Data> data(new Data());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800357 data->wireDecode(block);
358
359 PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
360 if (entry != pendingInterestTable_.end()) {
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800361 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800362 const OnData onData = (*entry)->getOnData();
363 const ptr_lib::shared_ptr<const Interest> interest = (*entry)->getInterest();
364 pendingInterestTable_.erase(entry);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800365
366 if (onData) {
367 onData(interest, data);
368 }
369
370 if (pendingInterestTable_.empty()) {
371 pitTimeoutCheckTimer_->cancel(); // this will cause checkPitExpire invocation
372 }
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800373 }
374 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700375}
376
Jeff Thompson0050abe2013-09-17 12:50:25 -0700377void
378Node::shutdown()
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700379{
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800380 pendingInterestTable_.clear();
381 registeredPrefixTable_.clear();
382
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700383 transport_->close();
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800384 pitTimeoutCheckTimer_->cancel();
385 processEventsTimeoutTimer_->cancel();
386 pitTimeoutCheckTimerActive_ = false;
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700387}
388
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800389Node::PendingInterestTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700390Node::getEntryIndexForExpressedInterest(const Name& name)
Jeff Thompson557b81e2013-08-21 15:13:51 -0700391{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800392 for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
393 i != pendingInterestTable_.end(); ++i)
394 {
395 if ((*i)->getInterest()->matchesName(name))
396 {
397 return i;
398 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700399 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800400
401 return pendingInterestTable_.end();
Jeff Thompson557b81e2013-08-21 15:13:51 -0700402}
Jeff Thompson86507bc2013-08-23 20:51:38 -0700403
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800404Node::RegisteredPrefixTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700405Node::getEntryForRegisteredPrefix(const Name& name)
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700406{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800407 RegisteredPrefixTable::iterator longestPrefix = registeredPrefixTable_.end();
408
409 for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
410 i != registeredPrefixTable_.end();
411 ++i)
412 {
413 if (longestPrefix == registeredPrefixTable_.end() ||
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800414 (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800415 {
416 longestPrefix = i;
417 }
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700418 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800419 return longestPrefix;
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700420}
421
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800422Node::PendingInterest::PendingInterest(const ptr_lib::shared_ptr<const Interest>& interest,
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800423 const OnData& onData, const OnTimeout& onTimeout)
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800424: interest_(interest),
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800425 onData_(onData), onTimeout_(onTimeout)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700426{
427 // Set up timeoutTime_.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800428 if (interest_->getInterestLifetime() >= 0)
429 timeoutTimeMilliseconds_ = ndn_getNowMilliseconds() + interest_->getInterestLifetime();
Jeff Thompson86507bc2013-08-23 20:51:38 -0700430 else
431 // No timeout.
Alexander Afanasyevb24a68a2013-12-28 16:53:21 -0800432 /**
433 * @todo Set more meaningful default timeout. This timeout MUST exist.
434 */
435 timeoutTimeMilliseconds_ = ndn_getNowMilliseconds() + 4000;
Jeff Thompson86507bc2013-08-23 20:51:38 -0700436}
437
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800438void
439Node::PendingInterest::callTimeout()
Jeff Thompson86507bc2013-08-23 20:51:38 -0700440{
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800441 if (onTimeout_) {
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800442 onTimeout_(interest_);
Jeff Thompson86507bc2013-08-23 20:51:38 -0700443 }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700444}
Jeff Thompson557b81e2013-08-21 15:13:51 -0700445
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700446}