blob: 5671269c366dcddc2dd6d0e18ffd04b6f193f240 [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>
Jeff Thompson9ae4d782013-10-17 10:25:54 -07009#include "c/util/time.h"
Alexander Afanasyev96d914f2014-01-02 22:24:29 -080010
Jeff Thompson25b4e612013-10-10 16:03:24 -070011#include <ndn-cpp/forwarding-entry.hpp>
Jeff Thompson25b4e612013-10-10 16:03:24 -070012#include <ndn-cpp/node.hpp>
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070013
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080014#include "util/ndnd-id-fetcher.hpp"
15
16#include <ndn-cpp/encoding/block.hpp>
Alexander Afanasyev96d914f2014-01-02 22:24:29 -080017
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070018using namespace std;
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070019
20namespace ndn {
21
Jeff Thompson62992e42013-10-07 18:50:51 -070022uint64_t Node::PendingInterest::lastPendingInterestId_ = 0;
23uint64_t Node::RegisteredPrefix::lastRegisteredPrefixId_ = 0;
Jeff Thompson11095142013-10-01 16:20:28 -070024
Alexander Afanasyev0b688dc2013-12-18 16:43:37 -080025Node::Node(const ptr_lib::shared_ptr<Transport>& transport)
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080026 : timer_ (ioService_)
27 , transport_(transport)
28 , ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
Jeff Thompson557b81e2013-08-21 15:13:51 -070029{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080030 timer_.expires_from_now(boost::posix_time::milliseconds(100));
31 timer_.async_wait(func_lib::bind(&Node::checkPitExpire, this));
Jeff Thompson557b81e2013-08-21 15:13:51 -070032}
33
Jeff Thompson62992e42013-10-07 18:50:51 -070034uint64_t
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080035Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070036{
Jeff Thompson86507bc2013-08-23 20:51:38 -070037 // TODO: Properly check if we are already connected to the expected host.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080038 if (!transport_->isConnected())
39 transport_->connect(ioService_, ptr_lib::bind(&Node::onReceiveElement, this, _1));
Jeff Thompson86507bc2013-08-23 20:51:38 -070040
Jeff Thompson62992e42013-10-07 18:50:51 -070041 uint64_t pendingInterestId = PendingInterest::getNextPendingInterestId();
Jeff Thompsonce115762013-12-18 14:59:56 -080042 pendingInterestTable_.push_back(ptr_lib::shared_ptr<PendingInterest>(new PendingInterest
43 (pendingInterestId, ptr_lib::shared_ptr<const Interest>(new Interest(interest)), onData, onTimeout)));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080044
45 transport_->send(interest.wireEncode());
Jeff Thompson11095142013-10-01 16:20:28 -070046
47 return pendingInterestId;
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070048}
49
Jeff Thompson11095142013-10-01 16:20:28 -070050void
Jeff Thompson62992e42013-10-07 18:50:51 -070051Node::removePendingInterest(uint64_t pendingInterestId)
Jeff Thompson11095142013-10-01 16:20:28 -070052{
53 // Go backwards through the list so we can erase entries.
54 // Remove all entries even though pendingInterestId should be unique.
55 for (int i = (int)pendingInterestTable_.size() - 1; i >= 0; --i) {
56 if (pendingInterestTable_[i]->getPendingInterestId() == pendingInterestId)
57 pendingInterestTable_.erase(pendingInterestTable_.begin() + i);
58 }
59}
60
Jeff Thompson62992e42013-10-07 18:50:51 -070061uint64_t
Jeff Thompson590ec232013-09-18 15:55:56 -070062Node::registerPrefix
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080063 (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -070064{
Jeff Thompson11095142013-10-01 16:20:28 -070065 // Get the registeredPrefixId now so we can return it to the caller.
Jeff Thompson62992e42013-10-07 18:50:51 -070066 uint64_t registeredPrefixId = RegisteredPrefix::getNextRegisteredPrefixId();
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080067 ptr_lib::shared_ptr<const Name> prefixPtr = ptr_lib::make_shared<const Name>(prefix);
68
Jeff Thompson86507bc2013-08-23 20:51:38 -070069 if (ndndId_.size() == 0) {
70 // First fetch the ndndId of the connected hub.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080071 NdndIdFetcher fetcher(ndndId_,
72 func_lib::bind(&Node::registerPrefixHelper, this,
73 registeredPrefixId, prefixPtr, onInterest, onRegisterFailed, flags),
74 func_lib::bind(onRegisterFailed, prefixPtr));
75
76 // @todo: Check if this crash
Jeff Thompsonce115762013-12-18 14:59:56 -080077 // 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 -080078 expressInterest(ndndIdFetcherInterest_, fetcher, fetcher);
Jeff Thompson86507bc2013-08-23 20:51:38 -070079 }
80 else
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080081 registerPrefixHelper(registeredPrefixId, prefixPtr, onInterest, onRegisterFailed, flags);
Jeff Thompson11095142013-10-01 16:20:28 -070082
83 return registeredPrefixId;
84}
85
86void
Jeff Thompson62992e42013-10-07 18:50:51 -070087Node::removeRegisteredPrefix(uint64_t registeredPrefixId)
Jeff Thompson11095142013-10-01 16:20:28 -070088{
89 // Go backwards through the list so we can erase entries.
90 // Remove all entries even though pendingInterestId should be unique.
91 for (int i = (int)registeredPrefixTable_.size() - 1; i >= 0; --i) {
92 if (registeredPrefixTable_[i]->getRegisteredPrefixId() == registeredPrefixId)
93 registeredPrefixTable_.erase(registeredPrefixTable_.begin() + i);
94 }
Jeff Thompson86507bc2013-08-23 20:51:38 -070095}
96
Jeff Thompson0050abe2013-09-17 12:50:25 -070097void
Jeff Thompson590ec232013-09-18 15:55:56 -070098Node::registerPrefixHelper
Jeff Thompsonce115762013-12-18 14:59:56 -080099 (uint64_t registeredPrefixId, const ptr_lib::shared_ptr<const Name>& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed,
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800100 const ForwardingFlags& flags)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700101{
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700102 // Create a ForwardingEntry.
Alexander Afanasyevfbdfa092013-12-28 20:44:49 -0800103
104 // AlexA: ndnd ignores any freshness that is larger than 3600 sec and sets 300 sec instead
105 // to register "forever" (=2000000000 sec), freshnessPeriod must be omitted
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800106 ForwardingEntry forwardingEntry("selfreg", *prefix, -1, flags, -1);
107 Block content = forwardingEntry.wireEncode();
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700108
109 // Set the ForwardingEntry as the content of a Data packet and sign.
110 Data data;
Jeff Thompsonc2b7b142013-09-12 15:29:04 -0700111 data.setContent(content);
Jeff Thompsonea141d72013-09-19 14:40:10 -0700112 // For now, self sign with an arbirary key. In the future, we may not require a signature to register.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800113 // selfregSign(data);
114 const Block &encodedData = data.wireEncode();
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700115
116 // Create an interest where the name has the encoded Data packet.
117 Name interestName;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700118 const uint8_t component0[] = "ndnx";
119 const uint8_t component2[] = "selfreg";
Jeff Thompson3a715632013-10-31 11:36:35 -0700120 interestName.append(component0, sizeof(component0) - 1);
121 interestName.append(ndndId_);
122 interestName.append(component2, sizeof(component2) - 1);
123 interestName.append(encodedData);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700124
125 Interest interest(interestName);
126 interest.setScope(1);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700127
128 // Save the onInterest callback and send the registration interest.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800129 registeredPrefixTable_.push_back(ptr_lib::make_shared<RegisteredPrefix>(registeredPrefixId, prefix, onInterest));
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700130
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800131 transport_->send(interest.wireEncode());
Jeff Thompson86507bc2013-08-23 20:51:38 -0700132}
133
Jeff Thompson0050abe2013-09-17 12:50:25 -0700134void
135Node::processEvents()
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700136{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800137 ioService_.run();
138
139 // auto_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(ioService_));
140 // work.reset(); // Allow run() to exit.
141}
142
143void
144Node::checkPitExpire()
145{
Jeff Thompson48917f02013-08-21 17:12:45 -0700146 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700147 MillisecondsSince1970 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson11095142013-10-01 16:20:28 -0700148 for (int i = (int)pendingInterestTable_.size() - 1; i >= 0; --i) {
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800149 if (pendingInterestTable_[i]->isTimedOut(nowMilliseconds)) {
150 // Save the PendingInterest and remove it from the PIT. Then call the callback.
Jeff Thompsonce115762013-12-18 14:59:56 -0800151 ptr_lib::shared_ptr<PendingInterest> pendingInterest = pendingInterestTable_[i];
Jeff Thompson11095142013-10-01 16:20:28 -0700152 pendingInterestTable_.erase(pendingInterestTable_.begin() + i);
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800153 pendingInterest->callTimeout();
Jeff Thompson48917f02013-08-21 17:12:45 -0700154
155 // Refresh now since the timeout callback might have delayed.
Jeff Thompson9ae4d782013-10-17 10:25:54 -0700156 nowMilliseconds = ndn_getNowMilliseconds();
Jeff Thompson48917f02013-08-21 17:12:45 -0700157 }
158 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800159
160 timer_.expires_from_now(boost::posix_time::milliseconds(100));
161 timer_.async_wait(func_lib::bind(&Node::checkPitExpire, this));
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700162}
163
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800164
Jeff Thompson0050abe2013-09-17 12:50:25 -0700165void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800166Node::onReceiveElement(const Block &block)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700167{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800168 if (block.type() == Tlv::Interest)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800169 {
170 ptr_lib::shared_ptr<Interest> interest(new Interest());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800171 interest->wireDecode(block);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700172
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800173 RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
174 if (entry != registeredPrefixTable_.end()) {
175 (*entry)->getOnInterest()((*entry)->getPrefix(), interest, *transport_, (*entry)->getRegisteredPrefixId());
176 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700177 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800178 else if (block.type() == Tlv::Data)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800179 {
180 ptr_lib::shared_ptr<Data> data(new Data());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800181 data->wireDecode(block);
182
183 PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
184 if (entry != pendingInterestTable_.end()) {
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800185 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800186 const OnData onData = (*entry)->getOnData();
187 const ptr_lib::shared_ptr<const Interest> interest = (*entry)->getInterest();
188 pendingInterestTable_.erase(entry);
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800189 onData(interest, data);
190 }
191 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700192}
193
Jeff Thompson0050abe2013-09-17 12:50:25 -0700194void
195Node::shutdown()
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700196{
197 transport_->close();
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800198 ioService_.stop();
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700199}
200
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800201Node::PendingInterestTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700202Node::getEntryIndexForExpressedInterest(const Name& name)
Jeff Thompson557b81e2013-08-21 15:13:51 -0700203{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800204 for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
205 i != pendingInterestTable_.end(); ++i)
206 {
207 if ((*i)->getInterest()->matchesName(name))
208 {
209 return i;
210 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700211 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800212
213 return pendingInterestTable_.end();
Jeff Thompson557b81e2013-08-21 15:13:51 -0700214}
Jeff Thompson86507bc2013-08-23 20:51:38 -0700215
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800216Node::RegisteredPrefixTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700217Node::getEntryForRegisteredPrefix(const Name& name)
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700218{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800219 RegisteredPrefixTable::iterator longestPrefix = registeredPrefixTable_.end();
220
221 for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
222 i != registeredPrefixTable_.end();
223 ++i)
224 {
225 if (longestPrefix == registeredPrefixTable_.end() ||
226 (*i)->getPrefix()->size() > (*longestPrefix)->getPrefix()->size())
227 {
228 longestPrefix = i;
229 }
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700230 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800231 return longestPrefix;
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700232}
233
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800234Node::PendingInterest::PendingInterest(uint64_t pendingInterestId,
235 const ptr_lib::shared_ptr<const Interest>& interest,
236 const OnData& onData, const OnTimeout& onTimeout)
237: pendingInterestId_(pendingInterestId),
238 interest_(interest),
239 onData_(onData), onTimeout_(onTimeout)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700240{
241 // Set up timeoutTime_.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800242 if (interest_->getInterestLifetime() >= 0)
243 timeoutTimeMilliseconds_ = ndn_getNowMilliseconds() + interest_->getInterestLifetime();
Jeff Thompson86507bc2013-08-23 20:51:38 -0700244 else
245 // No timeout.
Alexander Afanasyevee940312013-12-24 19:43:15 -0800246 timeoutTimeMilliseconds_ = -1;
Jeff Thompson86507bc2013-08-23 20:51:38 -0700247}
248
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800249void
250Node::PendingInterest::callTimeout()
Jeff Thompson86507bc2013-08-23 20:51:38 -0700251{
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800252 if (onTimeout_) {
253 // Ignore all exceptions.
254 try {
255 onTimeout_(interest_);
Jeff Thompson86507bc2013-08-23 20:51:38 -0700256 }
Jeff Thompson3b0ed532013-11-05 13:43:40 -0800257 catch (...) { }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700258 }
Jeff Thompson86507bc2013-08-23 20:51:38 -0700259}
Jeff Thompson557b81e2013-08-21 15:13:51 -0700260
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700261}