blob: bd7ce67de4dc758a1590f51d12e392f9c1e71b68 [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 Afanasyeve9fdb802014-02-05 17:36:51 -080012#include "security/signature-sha256-with-rsa.hpp"
13
14#include "util/time.hpp"
15#include "util/random.hpp"
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070016
Alexander Afanasyeve289b532014-02-09 22:14:44 -080017#include "management/ndnd-controller.hpp"
18#include "management/nfd-controller.hpp"
19
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070020namespace ndn {
21
Alexander Afanasyeve289b532014-02-09 22:14:44 -080022Node::Node(const shared_ptr<Transport>& transport, bool nfdMode/* = false*/)
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080023{
Alexander Afanasyeve289b532014-02-09 22:14:44 -080024 construct(transport, make_shared<boost::asio::io_service>(), nfdMode);
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080025}
26
Alexander Afanasyeve289b532014-02-09 22:14:44 -080027Node::Node(const shared_ptr<Transport>& transport,
28 const shared_ptr<boost::asio::io_service> &ioService,
29 bool nfdMode/* = false*/)
Jeff Thompson557b81e2013-08-21 15:13:51 -070030{
Alexander Afanasyeve289b532014-02-09 22:14:44 -080031 construct(transport, ioService, nfdMode);
32}
33
34void
35Node::construct(const shared_ptr<Transport>& transport,
36 const shared_ptr<boost::asio::io_service> &ioService,
37 bool nfdMode)
38{
39 pitTimeoutCheckTimerActive_ = false;
40 transport_ = transport;
41 ioService_ = ioService;
42
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080043 pitTimeoutCheckTimer_ = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
44 processEventsTimeoutTimer_ = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
Alexander Afanasyeve289b532014-02-09 22:14:44 -080045
46 if (nfdMode)
47 m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
48 else
49 m_fwController = make_shared<ndnd::Controller>(boost::ref(*this));
Jeff Thompson557b81e2013-08-21 15:13:51 -070050}
51
Alexander Afanasyeve289b532014-02-09 22:14:44 -080052
Alexander Afanasyevb790d952014-01-24 12:07:53 -080053const PendingInterestId*
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080054Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070055{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080056 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080057 transport_->connect(*ioService_,
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080058 bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -080059
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080060 shared_ptr<const Interest> interestToExpress(new Interest(interest));
Alexander Afanasyevb790d952014-01-24 12:07:53 -080061
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080062 ioService_->post(bind(&Node::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
Alexander Afanasyevb790d952014-01-24 12:07:53 -080063
64 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
65}
66
67void
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080068Node::asyncExpressInterest(const shared_ptr<const Interest> &interest,
69 const OnData& onData, const OnTimeout& onTimeout)
Alexander Afanasyevb790d952014-01-24 12:07:53 -080070{
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080071 pendingInterestTable_.push_back(shared_ptr<PendingInterest>(new PendingInterest
72 (interest, onData, onTimeout)));
Alexander Afanasyevb790d952014-01-24 12:07:53 -080073
74 transport_->send(interest->wireEncode());
Alexander Afanasyevbf082112014-01-09 14:27:55 -080075
76 if (!pitTimeoutCheckTimerActive_) {
77 pitTimeoutCheckTimerActive_ = true;
78 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080079 pitTimeoutCheckTimer_->async_wait(bind(&Node::checkPitExpire, this));
Alexander Afanasyevbf082112014-01-09 14:27:55 -080080 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -070081}
Alexander Afanasyevb790d952014-01-24 12:07:53 -080082
Jeff Thompson11095142013-10-01 16:20:28 -070083void
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080084Node::put(const Data &data)
85{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080086 if (!transport_->isConnected())
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -080087 transport_->connect(*ioService_,
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080088 bind(&Node::onReceiveElement, this, _1));
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -080089
90 transport_->send(data.wireEncode());
91}
92
93
94void
Alexander Afanasyevb790d952014-01-24 12:07:53 -080095Node::removePendingInterest(const PendingInterestId *pendingInterestId)
Jeff Thompson11095142013-10-01 16:20:28 -070096{
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -080097 ioService_->post(bind(&Node::asyncRemovePendingInterest, this, pendingInterestId));
Jeff Thompson11095142013-10-01 16:20:28 -070098}
99
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800100
101void
102Node::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
103{
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800104 pendingInterestTable_.remove_if(MatchPendingInterestId(pendingInterestId));
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800105}
106
107const RegisteredPrefixId*
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800108Node::setInterestFilter(const Name& prefix,
109 const OnInterest& onInterest,
110 const OnSetInterestFilterFailed& onSetInterestFilterFailed)
Jeff Thompson86507bc2013-08-23 20:51:38 -0700111{
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800112 shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800113
Alexander Afanasyeve289b532014-02-09 22:14:44 -0800114 m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
115 bind(&RegisteredPrefixTable::push_back, &registeredPrefixTable_, prefixToRegister),
116 bind(onSetInterestFilterFailed, prefixToRegister->getPrefix(), _1));
Jeff Thompson11095142013-10-01 16:20:28 -0700117
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800118 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
Jeff Thompson11095142013-10-01 16:20:28 -0700119}
120
121void
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800122Node::unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
123{
124 ioService_->post(bind(&Node::asyncUnsetInterestFilter, this, registeredPrefixId));
125}
126
127void
128Node::asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
Jeff Thompson11095142013-10-01 16:20:28 -0700129{
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800130 RegisteredPrefixTable::iterator i = std::find_if(registeredPrefixTable_.begin(), registeredPrefixTable_.end(),
131 MatchRegisteredPrefixId(registeredPrefixId));
132 if (i != registeredPrefixTable_.end())
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800133 {
Alexander Afanasyeve289b532014-02-09 22:14:44 -0800134 m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
135 bind(&RegisteredPrefixTable::erase, &registeredPrefixTable_, i),
136 Controller::FailCallback());
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800137 }
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800138
139 // there cannot be two registered prefixes with the same id. if there are, then something is broken
Jeff Thompson86507bc2013-08-23 20:51:38 -0700140}
141
Jeff Thompson0050abe2013-09-17 12:50:25 -0700142void
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800143Node::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700144{
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800145 try
146 {
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800147 if (timeout < 0)
148 {
149 // do not block if timeout is negative, but process pending events
150 ioService_->poll();
151 return;
152 }
153
154 if (timeout > 0)
155 {
156 processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
Jeff Thompson6e9fc182014-01-23 13:04:08 -0800157 processEventsTimeoutTimer_->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800158 }
159
160 if (keepThread) {
161 // work will ensure that ioService_ is running until work object exists
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800162 ioServiceWork_ = make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800163 }
164
Alexander Afanasyeve1b7a5d2013-12-29 16:23:52 -0800165 ioService_->run();
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800166 ioService_->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800167 }
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800168 catch(Node::ProcessEventsTimeout &)
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800169 {
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800170 // break
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800171 ioService_->reset();
Alexander Afanasyeva557d5a2013-12-28 21:59:03 -0800172 }
Alexander Afanasyev8995f542014-01-17 15:33:44 -0800173 catch(const std::exception &)
174 {
175 ioService_->reset();
176 pendingInterestTable_.clear();
177 registeredPrefixTable_.clear();
178 throw;
179 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800180}
181
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800182void
183Node::shutdown()
184{
185 pendingInterestTable_.clear();
186 registeredPrefixTable_.clear();
187
188 transport_->close();
189 pitTimeoutCheckTimer_->cancel();
190 processEventsTimeoutTimer_->cancel();
191 pitTimeoutCheckTimerActive_ = false;
192}
193
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800194void
Alexander Afanasyev3ae2da22013-12-29 15:50:04 -0800195Node::fireProcessEventsTimeout(const boost::system::error_code& error)
196{
197 if (!error) // can fire for some other reason, e.g., cancelled
198 throw Node::ProcessEventsTimeout();
199}
200
201void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800202Node::checkPitExpire()
203{
Jeff Thompson48917f02013-08-21 17:12:45 -0700204 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800205 MillisecondsSince1970 nowMilliseconds = getNowMilliseconds();
206
207 PendingInterestTable::iterator i = pendingInterestTable_.begin();
208 while (i != pendingInterestTable_.end())
209 {
210 if ((*i)->isTimedOut(nowMilliseconds))
211 {
212 // Save the PendingInterest and remove it from the PIT. Then call the callback.
213 shared_ptr<PendingInterest> pendingInterest = *i;
214
215 i = pendingInterestTable_.erase(i);
216
217 pendingInterest->callTimeout();
218 }
219 else
220 ++i;
Jeff Thompson48917f02013-08-21 17:12:45 -0700221 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800222
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800223 if (!pendingInterestTable_.empty()) {
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800224 pitTimeoutCheckTimerActive_ = true;
225
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800226 pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800227 pitTimeoutCheckTimer_->async_wait(bind(&Node::checkPitExpire, this));
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800228 }
229 else {
230 pitTimeoutCheckTimerActive_ = false;
231
232 if (registeredPrefixTable_.empty()) {
233 transport_->close();
Alexander Afanasyevf75a0aa2014-01-09 14:29:22 -0800234 if (!ioServiceWork_) {
235 processEventsTimeoutTimer_->cancel();
236 }
Alexander Afanasyevbf082112014-01-09 14:27:55 -0800237 }
238 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700239}
240
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800241
Jeff Thompson0050abe2013-09-17 12:50:25 -0700242void
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800243Node::onReceiveElement(const Block &block)
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700244{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800245 if (block.type() == Tlv::Interest)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800246 {
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800247 shared_ptr<Interest> interest(new Interest());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800248 interest->wireDecode(block);
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700249
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800250 RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
251 if (entry != registeredPrefixTable_.end()) {
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800252 (*entry)->getOnInterest()((*entry)->getPrefix().shared_from_this(), interest);
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800253 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700254 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800255 else if (block.type() == Tlv::Data)
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800256 {
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800257 shared_ptr<Data> data(new Data());
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800258 data->wireDecode(block);
259
260 PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
261 if (entry != pendingInterestTable_.end()) {
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800262 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800263 const OnData onData = (*entry)->getOnData();
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800264 const shared_ptr<const Interest> interest = (*entry)->getInterest();
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800265 pendingInterestTable_.erase(entry);
Alexander Afanasyevbc343ef2014-01-09 22:36:20 -0800266
267 if (onData) {
268 onData(interest, data);
269 }
270
271 if (pendingInterestTable_.empty()) {
272 pitTimeoutCheckTimer_->cancel(); // this will cause checkPitExpire invocation
273 }
Alexander Afanasyev96d914f2014-01-02 22:24:29 -0800274 }
275 }
Jeff Thompsonbf50a1a2013-08-20 18:01:01 -0700276}
277
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800278Node::PendingInterestTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700279Node::getEntryIndexForExpressedInterest(const Name& name)
Jeff Thompson557b81e2013-08-21 15:13:51 -0700280{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800281 for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
282 i != pendingInterestTable_.end(); ++i)
283 {
284 if ((*i)->getInterest()->matchesName(name))
285 {
286 return i;
287 }
Jeff Thompson557b81e2013-08-21 15:13:51 -0700288 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800289
290 return pendingInterestTable_.end();
Jeff Thompson557b81e2013-08-21 15:13:51 -0700291}
Jeff Thompson86507bc2013-08-23 20:51:38 -0700292
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800293Node::RegisteredPrefixTable::iterator
Jeff Thompson0050abe2013-09-17 12:50:25 -0700294Node::getEntryForRegisteredPrefix(const Name& name)
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700295{
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800296 RegisteredPrefixTable::iterator longestPrefix = registeredPrefixTable_.end();
297
298 for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
299 i != registeredPrefixTable_.end();
300 ++i)
301 {
302 if (longestPrefix == registeredPrefixTable_.end() ||
Alexander Afanasyevb790d952014-01-24 12:07:53 -0800303 (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800304 {
305 longestPrefix = i;
306 }
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700307 }
Alexander Afanasyeve2e0d752014-01-03 13:30:30 -0800308 return longestPrefix;
Jeff Thompson9cc4be42013-08-27 18:12:41 -0700309}
310
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800311} // namespace ndn