blob: 23e3185986c4aa4673532a33c39a733a30a5e4ec [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 Afanasyeve9fdb802014-02-05 17:36:51 -08008#include "node.hpp"
Alexander Afanasyev96d914f2014-01-02 22:24:29 -08009
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080010#include "forwarding-entry.hpp"
11#include "face-instance.hpp"
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080012#include "status-response.hpp"
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -080013#include "security/signature-sha256-with-rsa.hpp"
14
15#include "util/time.hpp"
16#include "util/random.hpp"
17#include "util/ndnd-id-fetcher.hpp"
Alexander Afanasyev18371872014-01-05 23:00:26 -080018
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070019using namespace std;
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080020#if NDN_CPP_HAVE_CXX11
21// In the std library, the placeholders are in a different namespace than boost.
22using namespace ndn::func_lib::placeholders;
23#endif
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070024
25namespace ndn {
26
Alexander Afanasyev0b688dc2013-12-18 16:43:37 -080027Node::Node(const ptr_lib::shared_ptr<Transport>& transport)
Alexander Afanasyevbf082112014-01-09 14:27:55 -080028 : pitTimeoutCheckTimerActive_(false)
29 , transport_(transport)
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080030 , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
31{
32 ioService_ = ptr_lib::make_shared<boost::asio::io_service>();
33 pitTimeoutCheckTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
34 processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080035}
36
37Node::Node(const ptr_lib::shared_ptr<Transport>& transport, const ptr_lib::shared_ptr<boost::asio::io_service> &ioService)
38 : ioService_(ioService)
Alexander Afanasyevbf082112014-01-09 14:27:55 -080039 , pitTimeoutCheckTimerActive_(false)
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080040 , transport_(transport)
41 , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
Jeff Thompson557b81e2013-08-21 15:13:51 -070042{
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080043 pitTimeoutCheckTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
44 processEventsTimeoutTimer_ = ptr_lib::make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
Jeff Thompson557b81e2013-08-21 15:13:51 -070045}
46
Alexander Afanasyevb790d952014-01-24 12:07:53 -080047const PendingInterestId*
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080048Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070049{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080050 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080051 transport_->connect(*ioService_,
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -080052 ptr_lib::bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080053
Alexander Afanasyevb790d952014-01-24 12:07:53 -080054 ptr_lib::shared_ptr<const Interest> interestToExpress(new Interest(interest));
55
56 ioService_->post(func_lib::bind(&Node::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
57
58 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
59}
60
61void
62Node::asyncExpressInterest(const ptr_lib::shared_ptr<const Interest> &interest, const OnData& onData, const OnTimeout& onTimeout)
63{
64 pendingInterestTable_.push_back(ptr_lib::shared_ptr<PendingInterest>(new PendingInterest
65 (interest, onData, onTimeout)));
66
67 transport_->send(interest->wireEncode());
Alexander Afanasyevbf082112014-01-09 14:27:55 -080068
69 if (!pitTimeoutCheckTimerActive_) {
70 pitTimeoutCheckTimerActive_ = true;
71 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
72 pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
73 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070074}
Alexander Afanasyevb790d952014-01-24 12:07:53 -080075
Jeff Thompson11095142013-10-01 16:20:28 -070076void
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080077Node::put(const Data &data)
78{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080079 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080080 transport_->connect(*ioService_,
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -080081 ptr_lib::bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080082
83 transport_->send(data.wireEncode());
84}
85
86
87void
Alexander Afanasyevb790d952014-01-24 12:07:53 -080088Node::removePendingInterest(const PendingInterestId *pendingInterestId)
Jeff Thompson11095142013-10-01 16:20:28 -070089{
Alexander Afanasyevb790d952014-01-24 12:07:53 -080090 ioService_->post(func_lib::bind(&Node::asyncRemovePendingInterest, this, pendingInterestId));
Jeff Thompson11095142013-10-01 16:20:28 -070091}
92
Alexander Afanasyevb790d952014-01-24 12:07:53 -080093
94void
95Node::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
96{
97 std::remove_if(pendingInterestTable_.begin(), pendingInterestTable_.end(),
98 MatchPendingInterestId(pendingInterestId));
99}
100
101const RegisteredPrefixId*
Jeff Thompson590ec232013-09-18 15:55:56 -0700102Node::registerPrefix
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800103 (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700104{
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800105 ptr_lib::shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800106
Jeff Thompson86507bc2013-08-23 20:51:38 -0700107 if (ndndId_.size() == 0) {
108 // First fetch the ndndId of the connected hub.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800109 NdndIdFetcher fetcher(ndndId_,
110 func_lib::bind(&Node::registerPrefixHelper, this,
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800111 prefixToRegister, onRegisterFailed, flags),
112 func_lib::bind(onRegisterFailed, prefixToRegister->getPrefix().shared_from_this()));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800113
114 // @todo: Check if this crash
Jeff Thompsonce115762013-12-18 14:59:56 -0800115 // 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 -0800116 expressInterest(ndndIdFetcherInterest_, fetcher, fetcher);
Jeff Thompson86507bc2013-08-23 20:51:38 -0700117 }
118 else
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800119 registerPrefixHelper(prefixToRegister, onRegisterFailed, flags);
Jeff Thompson11095142013-10-01 16:20:28 -0700120
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800121 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
Jeff Thompson11095142013-10-01 16:20:28 -0700122}
123
124void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800125Node::removeRegisteredPrefix(const RegisteredPrefixId *registeredPrefixId)
Jeff Thompson11095142013-10-01 16:20:28 -0700126{
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800127 RegisteredPrefixTable::iterator i = std::find_if(registeredPrefixTable_.begin(), registeredPrefixTable_.end(),
128 MatchRegisteredPrefixId(registeredPrefixId));
129 if (i != registeredPrefixTable_.end())
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800130 {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800131 ForwardingEntry forwardingEntry("unreg", (*i)->getPrefix(), faceId_);
132 Data data;
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -0800133 // This ensures uniqueness of each prefix registration commands
134 data.setName(Name().appendVersion(random::generateWord32()));
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800135 data.setContent(forwardingEntry.wireEncode());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800136
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800137 SignatureSha256WithRsa signature;
138 signature.setValue(Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>()));
139 data.setSignature(signature);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800140
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800141 // Create an interest where the name has the encoded Data packet.
142 Name interestName;
143 interestName.append("ndnx");
144 interestName.append(ndndId_);
145 interestName.append("unreg");
146 interestName.append(data.wireEncode());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800147
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800148 Interest interest(interestName);
149 interest.setScope(1);
150 interest.setInterestLifetime(1000);
Alexander Afanasyevfb44c972014-01-26 11:38:07 -0800151 interest.setMustBeFresh(true);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800152
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800153 expressInterest(interest, OnData(), OnTimeout());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800154
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800155 registeredPrefixTable_.erase(i);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800156 }
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800157
158 // there cannot be two registered prefixes with the same id. if there are, then something is broken
Jeff Thompson86507bc2013-08-23 20:51:38 -0700159}
160
Jeff Thompson0050abe2013-09-17 12:50:25 -0700161void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800162Node::registerPrefixHelper(const ptr_lib::shared_ptr<RegisteredPrefix> &prefixToRegister,
Alexander Afanasyev79100492014-01-03 15:35:38 -0800163 const OnRegisterFailed& onRegisterFailed,
164 const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700165{
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700166 // Create a ForwardingEntry.
Alexander Afanasyevfbdfa092013-12-28 20:44:49 -0800167
168 // AlexA: ndnd ignores any freshness that is larger than 3600 sec and sets 300 sec instead
169 // to register "forever" (=2000000000 sec), freshnessPeriod must be omitted
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800170 ForwardingEntry forwardingEntry("selfreg", prefixToRegister->getPrefix(), -1, flags, -1);
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800171 Block content = forwardingEntry.wireEncode();
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700172
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -0800173
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700174 // Set the ForwardingEntry as the content of a Data packet and sign.
175 Data data;
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -0800176 // This ensures uniqueness of each prefix registration commands
177 data.setName(Name().appendVersion(random::generateWord32()));
Jeff Thompsonc2b7b142013-09-12 15:29:04 -0700178 data.setContent(content);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700179
Alexander Afanasyev79100492014-01-03 15:35:38 -0800180 // Create an empty signature, since nobody going to verify it for now
181 // @todo In the future, we may require real signatures to do the registration
182 SignatureSha256WithRsa signature;
183 signature.setValue(Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>()));
184 data.setSignature(signature);
185
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700186 // Create an interest where the name has the encoded Data packet.
187 Name interestName;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800188 interestName.append("ndnx");
Jeff Thompson3a715632013-10-31 11:36:35 -0700189 interestName.append(ndndId_);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800190 interestName.append("selfreg");
Alexander Afanasyev79100492014-01-03 15:35:38 -0800191 interestName.append(data.wireEncode());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800192
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700193 Interest interest(interestName);
194 interest.setScope(1);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800195 interest.setInterestLifetime(1000);
Alexander Afanasyevfb44c972014-01-26 11:38:07 -0800196 interest.setMustBeFresh(true);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800197
198 expressInterest(interest,
199 func_lib::bind(&Node::registerPrefixFinal, this,
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800200 prefixToRegister, onRegisterFailed, _1, _2),
201 func_lib::bind(onRegisterFailed, prefixToRegister->getPrefix().shared_from_this()));
Alexander Afanasyev18371872014-01-05 23:00:26 -0800202}
203
204void
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800205Node::registerPrefixFinal(const ptr_lib::shared_ptr<RegisteredPrefix> &prefixToRegister,
Alexander Afanasyev18371872014-01-05 23:00:26 -0800206 const OnRegisterFailed& onRegisterFailed,
207 const ptr_lib::shared_ptr<const Interest>&, const ptr_lib::shared_ptr<Data>&data)
208{
209 Block content = data->getContent();
210 content.parse();
211
212 if (content.getAll().empty())
213 {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800214 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800215 return;
216 }
217
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800218 Block::element_iterator val = content.getAll().begin();
219
220 switch(val->type())
Alexander Afanasyev18371872014-01-05 23:00:26 -0800221 {
222 case Tlv::FaceManagement::ForwardingEntry:
223 {
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800224 ForwardingEntry entry;
225 entry.wireDecode(*val);
226
227 // Save the onInterest callback and send the registration interest.
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800228 registeredPrefixTable_.push_back(prefixToRegister);
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800229
230 /// @todo Notify user about successful registration
231
Alexander Afanasyev18371872014-01-05 23:00:26 -0800232 // succeeded
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800233 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800234 }
235 case Tlv::FaceManagement::StatusResponse:
236 {
237 // failed :(
238 StatusResponse resp;
Alexander Afanasyeve0c02f52013-12-28 20:44:25 -0800239 resp.wireDecode(*val);
Alexander Afanasyev18371872014-01-05 23:00:26 -0800240
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800241 // std::cerr << "StatusReponse: " << resp << std::endl;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800242
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800243 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800244 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800245 }
246 default:
247 {
248 // failed :(
249
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800250 onRegisterFailed(prefixToRegister->getPrefix().shared_from_this());
Alexander Afanasyev18371872014-01-05 23:00:26 -0800251 return;
Alexander Afanasyev18371872014-01-05 23:00:26 -0800252 }
253 }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700254}
255
Jeff Thompson0050abe2013-09-17 12:50:25 -0700256void
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800257Node::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700258{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800259 try
260 {
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800261 if (timeout < 0)
262 {
263 // do not block if timeout is negative, but process pending events
264 ioService_->poll();
265 return;
266 }
267
268 if (timeout > 0)
269 {
270 processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
Jeff Thompson6e9fc182014-01-23 13:04:08 -0800271 processEventsTimeoutTimer_->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800272 }
273
274 if (keepThread) {
275 // work will ensure that ioService_ is running until work object exists
276 ioServiceWork_ = ptr_lib::make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
277 }
278
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -0800279 ioService_->run();
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800280 ioService_->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800281 }
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800282 catch(Node::ProcessEventsTimeout &)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800283 {
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800284 // break
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800285 ioService_->reset();
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800286 }
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800287 catch(const std::exception &)
288 {
289 ioService_->reset();
290 pendingInterestTable_.clear();
291 registeredPrefixTable_.clear();
292 throw;
293 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800294}
295
296void
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800297Node::fireProcessEventsTimeout(const boost::system::error_code& error)
298{
299 if (!error) // can fire for some other reason, e.g., cancelled
300 throw Node::ProcessEventsTimeout();
301}
302
303void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800304Node::checkPitExpire()
305{
Jeff Thompson48917f02013-08-21 17:12:45 -0700306 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700307 MillisecondsSince1970 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson11095142013-10-01 16:20:28 -0700308 for (int i = (int)pendingInterestTable_.size() - 1; i >= 0; --i) {
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800309 if (pendingInterestTable_[i]->isTimedOut(nowMilliseconds)) {
310 // Save the PendingInterest and remove it from the PIT. Then call the callback.
Jeff Thompsonce115762013-12-18 14:59:56 -0800311 ptr_lib::shared_ptr<PendingInterest> pendingInterest = pendingInterestTable_[i];
Jeff Thompson11095142013-10-01 16:20:28 -0700312 pendingInterestTable_.erase(pendingInterestTable_.begin() + i);
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800313 pendingInterest->callTimeout();
Jeff Thompson48917f02013-08-21 17:12:45 -0700314
315 // Refresh now since the timeout callback might have delayed.
Jeff Thompson9ae4d782013-10-17 10:25:54 -0700316 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson48917f02013-08-21 17:12:45 -0700317 }
318 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800319
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800320 if (!pendingInterestTable_.empty()) {
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800321 pitTimeoutCheckTimerActive_ = true;
322
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800323 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
324 pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
325 }
326 else {
327 pitTimeoutCheckTimerActive_ = false;
328
329 if (registeredPrefixTable_.empty()) {
330 transport_->close();
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800331 if (!ioServiceWork_) {
332 processEventsTimeoutTimer_->cancel();
333 }
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800334 }
335 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700336}
337
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800338
Jeff Thompson0050abe2013-09-17 12:50:25 -0700339void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800340Node::onReceiveElement(const Block &block)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700341{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800342 if (block.type() == Tlv::Interest)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800343 {
344 ptr_lib::shared_ptr<Interest> interest(new Interest());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800345 interest->wireDecode(block);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700346
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800347 RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
348 if (entry != registeredPrefixTable_.end()) {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800349 (*entry)->getOnInterest()((*entry)->getPrefix().shared_from_this(), interest);
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800350 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700351 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800352 else if (block.type() == Tlv::Data)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800353 {
354 ptr_lib::shared_ptr<Data> data(new Data());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800355 data->wireDecode(block);
356
357 PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
358 if (entry != pendingInterestTable_.end()) {
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800359 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800360 const OnData onData = (*entry)->getOnData();
361 const ptr_lib::shared_ptr<const Interest> interest = (*entry)->getInterest();
362 pendingInterestTable_.erase(entry);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800363
364 if (onData) {
365 onData(interest, data);
366 }
367
368 if (pendingInterestTable_.empty()) {
369 pitTimeoutCheckTimer_->cancel(); // this will cause checkPitExpire invocation
370 }
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800371 }
372 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700373}
374
Jeff Thompson0050abe2013-09-17 12:50:25 -0700375void
376Node::shutdown()
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700377{
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800378 pendingInterestTable_.clear();
379 registeredPrefixTable_.clear();
380
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700381 transport_->close();
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800382 pitTimeoutCheckTimer_->cancel();
383 processEventsTimeoutTimer_->cancel();
384 pitTimeoutCheckTimerActive_ = false;
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700385}
386
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800387Node::PendingInterestTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700388Node::getEntryIndexForExpressedInterest(const Name& name)
Jeff Thompson557b81e2013-08-21 15:13:51 -0700389{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800390 for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
391 i != pendingInterestTable_.end(); ++i)
392 {
393 if ((*i)->getInterest()->matchesName(name))
394 {
395 return i;
396 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700397 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800398
399 return pendingInterestTable_.end();
Jeff Thompson557b81e2013-08-21 15:13:51 -0700400}
Jeff Thompson86507bc2013-08-23 20:51:38 -0700401
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800402Node::RegisteredPrefixTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700403Node::getEntryForRegisteredPrefix(const Name& name)
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700404{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800405 RegisteredPrefixTable::iterator longestPrefix = registeredPrefixTable_.end();
406
407 for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
408 i != registeredPrefixTable_.end();
409 ++i)
410 {
411 if (longestPrefix == registeredPrefixTable_.end() ||
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800412 (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800413 {
414 longestPrefix = i;
415 }
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700416 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800417 return longestPrefix;
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700418}
419
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800420Node::PendingInterest::PendingInterest(const ptr_lib::shared_ptr<const Interest>& interest,
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800421 const OnData& onData, const OnTimeout& onTimeout)
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800422: interest_(interest),
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800423 onData_(onData), onTimeout_(onTimeout)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700424{
425 // Set up timeoutTime_.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800426 if (interest_->getInterestLifetime() >= 0)
427 timeoutTimeMilliseconds_ = ndn_getNowMilliseconds() + interest_->getInterestLifetime();
Jeff Thompson86507bc2013-08-23 20:51:38 -0700428 else
429 // No timeout.
Alexander Afanasyevb24a68a2013-12-28 16:53:21 -0800430 /**
431 * @todo Set more meaningful default timeout. This timeout MUST exist.
432 */
433 timeoutTimeMilliseconds_ = ndn_getNowMilliseconds() + 4000;
Jeff Thompson86507bc2013-08-23 20:51:38 -0700434}
435
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800436void
437Node::PendingInterest::callTimeout()
Jeff Thompson86507bc2013-08-23 20:51:38 -0700438{
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800439 if (onTimeout_) {
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800440 onTimeout_(interest_);
Jeff Thompson86507bc2013-08-23 20:51:38 -0700441 }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700442}
Jeff Thompson557b81e2013-08-21 15:13:51 -0700443
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700444}