blob: aef13af015ac09068aeceb6353a5a09bb8dc70d0 [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"
Yingdi Yuf9fa52f2014-02-06 12:27:32 -080020#include "encoding/tlv-nfd-control.hpp"
Jeff Thompsonb982b6d2013-07-15 18:15:45 -070021
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070022namespace ndn {
Alexander Afanasyevb790d952014-01-24 12:07:53 -080023
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080024Face::Face()
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070025{
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080026 construct(shared_ptr<Transport>(new UnixTransport()),
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080027 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080028}
29
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080030Face::Face(const shared_ptr<boost::asio::io_service> &ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080031{
32 construct(shared_ptr<Transport>(new UnixTransport()),
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080033 ioService);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080034}
35
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080036Face::Face(const std::string &host, const std::string &port/* = "6363"*/)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080037{
38 construct(shared_ptr<Transport>(new TcpTransport(host, port)),
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080039 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080040}
41
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080042Face::Face(const shared_ptr<Transport>& transport)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080043{
44 construct(transport,
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080045 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080046}
47
48Face::Face(const shared_ptr<Transport>& transport,
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080049 const shared_ptr<boost::asio::io_service> &ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080050{
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080051 construct(transport, ioService);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080052}
53
54void
55Face::construct(const shared_ptr<Transport>& transport,
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080056 const shared_ptr<boost::asio::io_service> &ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080057{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080058 m_pitTimeoutCheckTimerActive = false;
59 m_transport = transport;
60 m_ioService = ioService;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080061
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080062 m_pitTimeoutCheckTimer = make_shared<boost::asio::deadline_timer>(boost::ref(*m_ioService));
63 m_processEventsTimeoutTimer = make_shared<boost::asio::deadline_timer>(boost::ref(*m_ioService));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -080064
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080065 if (std::getenv("NFD") != 0)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080066 m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070067 else
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080068 m_fwController = make_shared<ndnd::Controller>(boost::ref(*this));
69}
70
71
72const PendingInterestId*
73Face::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
74{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080075 if (!m_transport->isConnected())
76 m_transport->connect(*m_ioService,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080077 bind(&Face::onReceiveElement, this, _1));
78
79 shared_ptr<const Interest> interestToExpress(new Interest(interest));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -080080
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080081 m_ioService->post(bind(&Face::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -080082
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080083 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
84}
85
86const PendingInterestId*
87Face::expressInterest(const Name& name,
88 const Interest &tmpl,
89 const OnData& onData, const OnTimeout& onTimeout/* = OnTimeout()*/)
90{
91 return expressInterest(Interest(name,
92 tmpl.getMinSuffixComponents(),
93 tmpl.getMaxSuffixComponents(),
94 tmpl.getExclude(),
95 tmpl.getChildSelector(),
96 tmpl.getMustBeFresh(),
97 tmpl.getScope(),
98 tmpl.getInterestLifetime()),
99 onData, onTimeout);
100}
101
102void
103Face::asyncExpressInterest(const shared_ptr<const Interest> &interest,
104 const OnData& onData, const OnTimeout& onTimeout)
105{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800106 m_pendingInterestTable.push_back(shared_ptr<PendingInterest>(new PendingInterest
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800107 (interest, onData, onTimeout)));
108
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800109 m_transport->send(interest->wireEncode());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800110
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800111 if (!m_pitTimeoutCheckTimerActive) {
112 m_pitTimeoutCheckTimerActive = true;
113 m_pitTimeoutCheckTimer->expires_from_now(boost::posix_time::milliseconds(100));
114 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800115 }
116}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800117
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800118void
119Face::put(const Data &data)
120{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800121 if (!m_transport->isConnected())
122 m_transport->connect(*m_ioService,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800123 bind(&Face::onReceiveElement, this, _1));
124
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800125 m_transport->send(data.wireEncode());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800126}
127
128
129void
130Face::removePendingInterest(const PendingInterestId *pendingInterestId)
131{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800132 m_ioService->post(bind(&Face::asyncRemovePendingInterest, this, pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800133}
134
135
136void
137Face::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
138{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800139 m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800140}
141
142const RegisteredPrefixId*
143Face::setInterestFilter(const Name& prefix,
144 const OnInterest& onInterest,
145 const OnSetInterestFilterFailed& onSetInterestFilterFailed)
146{
147 shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
148
149 m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800150 bind(&RegisteredPrefixTable::push_back, &m_registeredPrefixTable, prefixToRegister),
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800151 bind(onSetInterestFilterFailed, prefixToRegister->getPrefix(), _1));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800152
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800153 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
154}
155
156void
157Face::unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
158{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800159 m_ioService->post(bind(&Face::asyncUnsetInterestFilter, this, registeredPrefixId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800160}
161
162void
163Face::asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
164{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800165 RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(), m_registeredPrefixTable.end(),
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800166 MatchRegisteredPrefixId(registeredPrefixId));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800167 if (i != m_registeredPrefixTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800168 {
169 m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800170 bind(&Face::finalizeUnsertInterestFilter, this, i),
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800171 Controller::FailCallback());
172 }
173
174 // there cannot be two registered prefixes with the same id. if there are, then something is broken
175}
176
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800177void
178Face::finalizeUnsertInterestFilter(RegisteredPrefixTable::iterator item)
179{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800180 m_registeredPrefixTable.erase(item);
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800181
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800182 if (!m_pitTimeoutCheckTimerActive && m_registeredPrefixTable.empty())
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800183 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800184 m_transport->close();
185 if (!m_ioServiceWork) {
186 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800187 }
188 }
189}
190
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800191void
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800192Face::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
193{
194 try
195 {
196 if (timeout < 0)
197 {
198 // do not block if timeout is negative, but process pending events
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800199 m_ioService->poll();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800200 return;
201 }
202
203 if (timeout > 0)
204 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800205 m_processEventsTimeoutTimer->expires_from_now(boost::posix_time::milliseconds(timeout));
206 m_processEventsTimeoutTimer->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800207 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800208
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800209 if (keepThread) {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800210 // work will ensure that m_ioService is running until work object exists
211 m_ioServiceWork = make_shared<boost::asio::io_service::work>(boost::ref(*m_ioService));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800212 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800213
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800214 m_ioService->run();
215 m_ioService->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800216 }
217 catch(Face::ProcessEventsTimeout &)
218 {
219 // break
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800220 m_ioService->reset();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800221 }
222 catch(const std::exception &)
223 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800224 m_ioService->reset();
225 m_pendingInterestTable.clear();
226 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800227 throw;
228 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700229}
230
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800231void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700232Face::shutdown()
Jeff Thompson517ffa82013-08-05 16:04:34 -0700233{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800234 m_pendingInterestTable.clear();
235 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800236
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800237 m_transport->close();
238 m_pitTimeoutCheckTimer->cancel();
239 m_processEventsTimeoutTimer->cancel();
240 m_pitTimeoutCheckTimerActive = false;
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700241}
242
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800243void
244Face::fireProcessEventsTimeout(const boost::system::error_code& error)
245{
246 if (!error) // can fire for some other reason, e.g., cancelled
247 throw Face::ProcessEventsTimeout();
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700248}
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800249
250void
251Face::checkPitExpire()
252{
253 // Check for PIT entry timeouts. Go backwards through the list so we can erase entries.
254 MillisecondsSince1970 nowMilliseconds = getNowMilliseconds();
255
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800256 PendingInterestTable::iterator i = m_pendingInterestTable.begin();
257 while (i != m_pendingInterestTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800258 {
259 if ((*i)->isTimedOut(nowMilliseconds))
260 {
261 // Save the PendingInterest and remove it from the PIT. Then call the callback.
262 shared_ptr<PendingInterest> pendingInterest = *i;
263
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800264 i = m_pendingInterestTable.erase(i);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800265
266 pendingInterest->callTimeout();
267 }
268 else
269 ++i;
270 }
271
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800272 if (!m_pendingInterestTable.empty()) {
273 m_pitTimeoutCheckTimerActive = true;
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800274
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800275 m_pitTimeoutCheckTimer->expires_from_now(boost::posix_time::milliseconds(100));
276 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800277 }
278 else {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800279 m_pitTimeoutCheckTimerActive = false;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800280
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800281 if (m_registeredPrefixTable.empty()) {
282 m_transport->close();
283 if (!m_ioServiceWork) {
284 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800285 }
286 }
287 }
288}
289
290
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800291void
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800292Face::onReceiveElement(const Block &blockFromDaemon)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800293{
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800294 Block block = blockFromDaemon;
295 uint64_t incomingFaceId = std::numeric_limits<uint64_t>::max();
296 if (block.type() == tlv::nfd_control::LocalControlHeader)
297 block = wireDecodeLocalControlHeader(block, incomingFaceId);
298
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800299 if (block.type() == Tlv::Interest)
300 {
301 shared_ptr<Interest> interest(new Interest());
302 interest->wireDecode(block);
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800303 interest->setIncomingFaceId(incomingFaceId);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800304
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800305 RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800306 if (entry != m_registeredPrefixTable.end()) {
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800307 (*entry)->getOnInterest()((*entry)->getPrefix(), *interest);
308 }
309 }
310 else if (block.type() == Tlv::Data)
311 {
312 shared_ptr<Data> data(new Data());
313 data->wireDecode(block);
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800314 data->setIncomingFaceId(incomingFaceId);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800315
316 PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800317 if (entry != m_pendingInterestTable.end()) {
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800318 // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
319 const OnData onData = (*entry)->getOnData();
320 const shared_ptr<const Interest> interest = (*entry)->getInterest();
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800321 m_pendingInterestTable.erase(entry);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800322
323 if (onData) {
324 onData(*interest, *data);
325 }
326
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800327 if (m_pendingInterestTable.empty()) {
328 m_pitTimeoutCheckTimer->cancel(); // this will cause checkPitExpire invocation
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800329 }
330 }
331 }
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800332 // ignore any other type
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800333}
334
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800335Face::PendingInterestTable::iterator
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800336Face::getEntryIndexForExpressedInterest(const Name& name)
337{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800338 for (PendingInterestTable::iterator i = m_pendingInterestTable.begin ();
339 i != m_pendingInterestTable.end(); ++i)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800340 {
341 if ((*i)->getInterest()->matchesName(name))
342 {
343 return i;
344 }
345 }
346
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800347 return m_pendingInterestTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800348}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800349
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800350Face::RegisteredPrefixTable::iterator
351Face::getEntryForRegisteredPrefix(const Name& name)
352{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800353 RegisteredPrefixTable::iterator longestPrefix = m_registeredPrefixTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800354
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800355 for (RegisteredPrefixTable::iterator i = m_registeredPrefixTable.begin();
356 i != m_registeredPrefixTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800357 ++i)
358 {
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800359 if ((*i)->getPrefix().isPrefixOf(name))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800360 {
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800361
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800362 if (longestPrefix == m_registeredPrefixTable.end() ||
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800363 (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
364 {
365 longestPrefix = i;
366 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800367 }
368 }
369 return longestPrefix;
370}
371
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800372Block
373Face::wireEncodeLocalControlHeader(const Block& blockWithoutHeader, uint64_t nextHopFaceId)
374{
375 Block localControlHeader = Block(tlv::nfd_control::LocalControlHeader);
376 Block localControlInfo = Block(tlv::nfd_control::LocalControlInfo);
377
378 localControlInfo.push_back
379 (nonNegativeIntegerBlock(tlv::nfd_control::NextHopFaceId, nextHopFaceId));
380
381 localControlHeader.push_back(localControlInfo);
382 localControlHeader.push_back(blockWithoutHeader);
383
384 localControlHeader.encode();
385 return localControlHeader;
386}
387
388Block
389Face::wireDecodeLocalControlHeader(const Block& blockWithHeader, uint64_t& incomingFaceId)
390{
391 blockWithHeader.parse();
392 if (blockWithHeader.elements_size() != 2 ||
393 blockWithHeader.elements_begin()->type() != tlv::nfd_control::LocalControlInfo)
394 {
395 return Block();
396 }
397
398 const Block& localControlInfo = *blockWithHeader.elements_begin();
399 localControlInfo.parse();
400
401 Block::element_const_iterator i = localControlInfo.find(tlv::nfd_control::IncomingFaceId);
402 if (i != localControlInfo.elements_end())
403 {
404 incomingFaceId = readNonNegativeInteger(*i);
405 }
406
407 return *blockWithHeader.elements().rbegin();
408}
409
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800410} // namespace ndn