blob: e36286476b97be430e2accca6450d19d12c66b0f [file] [log] [blame]
Jeff Thompson25b4e612013-10-10 16:03:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -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 Thompsonaa4e6db2013-07-15 17:25:23 -07005 * See COPYING for copyright and distribution information.
6 */
7
Alexander Afanasyev0222fba2014-02-09 23:16:02 -08008#include "common.hpp"
9
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080010#include "face.hpp"
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070011
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080012#include "security/signature-sha256-with-rsa.hpp"
13
14#include "util/time.hpp"
15#include "util/random.hpp"
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080016#include <cstdlib>
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080017
18#include "management/ndnd-controller.hpp"
19#include "management/nfd-controller.hpp"
Jeff Thompsonb982b6d2013-07-15 18:15:45 -070020
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070021namespace ndn {
Alexander Afanasyevb790d952014-01-24 12:07:53 -080022
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080023Face::Face()
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070024{
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080025 construct(shared_ptr<Transport>(new UnixTransport()),
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080026 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080027}
28
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080029Face::Face(const shared_ptr<boost::asio::io_service> &ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080030{
31 construct(shared_ptr<Transport>(new UnixTransport()),
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080032 ioService);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080033}
34
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080035Face::Face(const std::string &host, const std::string &port/* = "6363"*/)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080036{
37 construct(shared_ptr<Transport>(new TcpTransport(host, port)),
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080038 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080039}
40
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080041Face::Face(const shared_ptr<Transport>& transport)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080042{
43 construct(transport,
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080044 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080045}
46
47Face::Face(const shared_ptr<Transport>& transport,
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080048 const shared_ptr<boost::asio::io_service> &ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080049{
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080050 construct(transport, ioService);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080051}
52
53void
54Face::construct(const shared_ptr<Transport>& transport,
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080055 const shared_ptr<boost::asio::io_service> &ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080056{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080057 m_pitTimeoutCheckTimerActive = false;
58 m_transport = transport;
59 m_ioService = ioService;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080060
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080061 m_pitTimeoutCheckTimer = make_shared<boost::asio::deadline_timer>(boost::ref(*m_ioService));
62 m_processEventsTimeoutTimer = make_shared<boost::asio::deadline_timer>(boost::ref(*m_ioService));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -080063
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080064 if (std::getenv("NFD") != 0)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080065 m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070066 else
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080067 m_fwController = make_shared<ndnd::Controller>(boost::ref(*this));
68}
69
70
71const PendingInterestId*
72Face::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
73{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080074 if (!m_transport->isConnected())
75 m_transport->connect(*m_ioService,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080076 bind(&Face::onReceiveElement, this, _1));
77
78 shared_ptr<const Interest> interestToExpress(new Interest(interest));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -080079
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080080 m_ioService->post(bind(&Face::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -080081
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080082 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
83}
84
85const PendingInterestId*
86Face::expressInterest(const Name& name,
87 const Interest &tmpl,
88 const OnData& onData, const OnTimeout& onTimeout/* = OnTimeout()*/)
89{
90 return expressInterest(Interest(name,
91 tmpl.getMinSuffixComponents(),
92 tmpl.getMaxSuffixComponents(),
93 tmpl.getExclude(),
94 tmpl.getChildSelector(),
95 tmpl.getMustBeFresh(),
96 tmpl.getScope(),
97 tmpl.getInterestLifetime()),
98 onData, onTimeout);
99}
100
101void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800102Face::asyncExpressInterest(const shared_ptr<const Interest>& interest,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800103 const OnData& onData, const OnTimeout& onTimeout)
104{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800105 m_pendingInterestTable.push_back(shared_ptr<PendingInterest>(new PendingInterest
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800106 (interest, onData, onTimeout)));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800107
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800108 if (!interest->getLocalControlHeader().empty(false, true))
109 {
110 // encode only NextHopFaceId towards the forwarder
111 m_transport->send(interest->getLocalControlHeader().wireEncode(*interest, false, true),
112 interest->wireEncode());
113 }
114 else
115 {
116 m_transport->send(interest->wireEncode());
117 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800118
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800119 if (!m_pitTimeoutCheckTimerActive) {
120 m_pitTimeoutCheckTimerActive = true;
121 m_pitTimeoutCheckTimer->expires_from_now(boost::posix_time::milliseconds(100));
122 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800123 }
124}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800125
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800126void
127Face::put(const Data &data)
128{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800129 if (!m_transport->isConnected())
130 m_transport->connect(*m_ioService,
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800131 bind(&Face::onReceiveElement, this, _1));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800132
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800133 if (!data.getLocalControlHeader().empty(false, true))
134 {
135 m_transport->send(data.wireEncode());
136 }
137 else
138 {
139 m_transport->send(data.getLocalControlHeader().wireEncode(data, false, true),
140 data.wireEncode());
141 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800142}
143
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800144void
145Face::removePendingInterest(const PendingInterestId *pendingInterestId)
146{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800147 m_ioService->post(bind(&Face::asyncRemovePendingInterest, this, pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800148}
149
150
151void
152Face::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
153{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800154 m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800155}
156
157const RegisteredPrefixId*
158Face::setInterestFilter(const Name& prefix,
159 const OnInterest& onInterest,
160 const OnSetInterestFilterFailed& onSetInterestFilterFailed)
161{
162 shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
163
164 m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800165 bind(&RegisteredPrefixTable::push_back, &m_registeredPrefixTable, prefixToRegister),
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800166 bind(onSetInterestFilterFailed, prefixToRegister->getPrefix(), _1));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800167
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800168 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
169}
170
171void
172Face::unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
173{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800174 m_ioService->post(bind(&Face::asyncUnsetInterestFilter, this, registeredPrefixId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800175}
176
177void
178Face::asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
179{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800180 RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(), m_registeredPrefixTable.end(),
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800181 MatchRegisteredPrefixId(registeredPrefixId));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800182 if (i != m_registeredPrefixTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800183 {
184 m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800185 bind(&Face::finalizeUnsertInterestFilter, this, i),
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800186 Controller::FailCallback());
187 }
188
189 // there cannot be two registered prefixes with the same id. if there are, then something is broken
190}
191
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800192void
193Face::finalizeUnsertInterestFilter(RegisteredPrefixTable::iterator item)
194{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800195 m_registeredPrefixTable.erase(item);
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800196
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800197 if (!m_pitTimeoutCheckTimerActive && m_registeredPrefixTable.empty())
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800198 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800199 m_transport->close();
200 if (!m_ioServiceWork) {
201 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800202 }
203 }
204}
205
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800206void
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800207Face::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
208{
209 try
210 {
211 if (timeout < 0)
212 {
213 // do not block if timeout is negative, but process pending events
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800214 m_ioService->poll();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800215 return;
216 }
217
218 if (timeout > 0)
219 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800220 m_processEventsTimeoutTimer->expires_from_now(boost::posix_time::milliseconds(timeout));
221 m_processEventsTimeoutTimer->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800222 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800223
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800224 if (keepThread) {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800225 // work will ensure that m_ioService is running until work object exists
226 m_ioServiceWork = make_shared<boost::asio::io_service::work>(boost::ref(*m_ioService));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800227 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800228
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800229 m_ioService->run();
230 m_ioService->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800231 }
232 catch(Face::ProcessEventsTimeout &)
233 {
234 // break
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800235 m_ioService->reset();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800236 }
237 catch(const std::exception &)
238 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800239 m_ioService->reset();
240 m_pendingInterestTable.clear();
241 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800242 throw;
243 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700244}
245
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800246void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700247Face::shutdown()
Jeff Thompson517ffa82013-08-05 16:04:34 -0700248{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800249 m_pendingInterestTable.clear();
250 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800251
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800252 m_transport->close();
253 m_pitTimeoutCheckTimer->cancel();
254 m_processEventsTimeoutTimer->cancel();
255 m_pitTimeoutCheckTimerActive = false;
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700256}
257
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800258void
259Face::fireProcessEventsTimeout(const boost::system::error_code& error)
260{
261 if (!error) // can fire for some other reason, e.g., cancelled
262 throw Face::ProcessEventsTimeout();
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700263}
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800264
265void
266Face::checkPitExpire()
267{
268 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
269 MillisecondsSince1970 nowMilliseconds = getNowMilliseconds();
270
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800271 PendingInterestTable::iterator i = m_pendingInterestTable.begin();
272 while (i != m_pendingInterestTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800273 {
274 if ((*i)->isTimedOut(nowMilliseconds))
275 {
276 // Save the PendingInterest and remove it from the PIT. Then call the callback.
277 shared_ptr<PendingInterest> pendingInterest = *i;
278
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800279 i = m_pendingInterestTable.erase(i);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800280
281 pendingInterest->callTimeout();
282 }
283 else
284 ++i;
285 }
286
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800287 if (!m_pendingInterestTable.empty()) {
288 m_pitTimeoutCheckTimerActive = true;
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800289
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800290 m_pitTimeoutCheckTimer->expires_from_now(boost::posix_time::milliseconds(100));
291 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800292 }
293 else {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800294 m_pitTimeoutCheckTimerActive = false;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800295
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800296 if (m_registeredPrefixTable.empty()) {
297 m_transport->close();
298 if (!m_ioServiceWork) {
299 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800300 }
301 }
302 }
303}
304
305
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800306void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800307Face::onReceiveElement(const Block& blockFromDaemon)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800308{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800309 const Block& block = nfd::LocalControlHeader::getPayload(blockFromDaemon);
310
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800311 if (block.type() == Tlv::Interest)
312 {
313 shared_ptr<Interest> interest(new Interest());
314 interest->wireDecode(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800315 if (&block != &blockFromDaemon)
316 interest->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800317
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800318 RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800319 if (entry != m_registeredPrefixTable.end()) {
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800320 (*entry)->getOnInterest()((*entry)->getPrefix(), *interest);
321 }
322 }
323 else if (block.type() == Tlv::Data)
324 {
325 shared_ptr<Data> data(new Data());
326 data->wireDecode(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800327 if (&block != &blockFromDaemon)
328 data->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800329
330 PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800331 if (entry != m_pendingInterestTable.end()) {
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800332 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
333 const OnData onData = (*entry)->getOnData();
334 const shared_ptr<const Interest> interest = (*entry)->getInterest();
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800335 m_pendingInterestTable.erase(entry);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800336
337 if (onData) {
338 onData(*interest, *data);
339 }
340
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800341 if (m_pendingInterestTable.empty()) {
342 m_pitTimeoutCheckTimer->cancel(); // this will cause checkPitExpire invocation
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800343 }
344 }
345 }
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800346 // ignore any other type
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800347}
348
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800349Face::PendingInterestTable::iterator
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800350Face::getEntryIndexForExpressedInterest(const Name& name)
351{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800352 for (PendingInterestTable::iterator i = m_pendingInterestTable.begin ();
353 i != m_pendingInterestTable.end(); ++i)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800354 {
355 if ((*i)->getInterest()->matchesName(name))
356 {
357 return i;
358 }
359 }
360
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800361 return m_pendingInterestTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800362}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800363
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800364Face::RegisteredPrefixTable::iterator
365Face::getEntryForRegisteredPrefix(const Name& name)
366{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800367 RegisteredPrefixTable::iterator longestPrefix = m_registeredPrefixTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800368
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800369 for (RegisteredPrefixTable::iterator i = m_registeredPrefixTable.begin();
370 i != m_registeredPrefixTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800371 ++i)
372 {
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800373 if ((*i)->getPrefix().isPrefixOf(name))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800374 {
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800375
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800376 if (longestPrefix == m_registeredPrefixTable.end() ||
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800377 (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
378 {
379 longestPrefix = i;
380 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800381 }
382 }
383 return longestPrefix;
384}
385
386} // namespace ndn