blob: f91a8f8fd0d7376fdcb1baa2ec31abf046346c7c [file] [log] [blame]
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology
9 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070024
25#include "face-manager.hpp"
26
Davide Pesavento52a18f92014-04-10 00:55:01 +020027#include "face-flags.hpp"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060028#include "core/logger.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070029#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060030#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070031#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070032#include "face/tcp-factory.hpp"
33#include "face/udp-factory.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070034#include "core/config-file.hpp"
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060035
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060036#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060038#endif // HAVE_UNIX_SOCKETS
39
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070040#ifdef HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041#include "face/ethernet-factory.hpp"
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070042#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043
Wentao Shang53df1632014-04-21 12:01:32 -070044#ifdef HAVE_WEBSOCKET
45#include "face/websocket-factory.hpp"
46#endif // HAVE_WEBSOCKET
47
Alexander Afanasyev4a771362014-04-24 21:29:33 -070048#include <ndn-cxx/management/nfd-face-event-notification.hpp>
Davide Pesavento52a18f92014-04-10 00:55:01 +020049
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070050namespace nfd {
51
52NFD_LOG_INIT("FaceManager");
53
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060054const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070055
56const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
57 FaceManager::COMMAND_PREFIX.size() +
58 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060059 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070060
61const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
62 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070063 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070064
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060065const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070066 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060067 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060068 Name::Component("create"),
69 &FaceManager::createFace
70 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070071
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060072 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060073 Name::Component("destroy"),
74 &FaceManager::destroyFace
75 ),
76
77 SignedVerbAndProcessor(
78 Name::Component("enable-local-control"),
79 &FaceManager::enableLocalControl
80 ),
81
82 SignedVerbAndProcessor(
83 Name::Component("disable-local-control"),
84 &FaceManager::disableLocalControl
85 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070086 };
87
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060088const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
89 {
90 UnsignedVerbAndProcessor(
91 Name::Component("list"),
92 &FaceManager::listFaces
93 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060094
95 UnsignedVerbAndProcessor(
96 Name::Component("events"),
97 &FaceManager::ignoreUnsignedVerb
98 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060099 };
100
101const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
102const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
103
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600104const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700105
106FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700107 shared_ptr<InternalFace> face)
108 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700109 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600110 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600111 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600112 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600113 SIGNED_COMMAND_VERBS +
114 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600115 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600116 UNSIGNED_COMMAND_VERBS +
117 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600118
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700119{
120 face->setInterestFilter("/localhost/nfd/faces",
121 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600122
123 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
124 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700125}
126
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600127FaceManager::~FaceManager()
128{
129
130}
131
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700132void
133FaceManager::setConfigFile(ConfigFile& configFile)
134{
135 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600136 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700137}
138
139
140void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600141FaceManager::onConfig(const ConfigSection& configSection,
142 bool isDryRun,
143 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700144{
145 bool hasSeenUnix = false;
146 bool hasSeenTcp = false;
147 bool hasSeenUdp = false;
148 bool hasSeenEther = false;
Wentao Shang53df1632014-04-21 12:01:32 -0700149 bool hasSeenWebSocket = false;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700150
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600151 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
152
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700153 for (ConfigSection::const_iterator item = configSection.begin();
154 item != configSection.end();
155 ++item)
156 {
157 if (item->first == "unix")
158 {
159 if (hasSeenUnix)
160 throw Error("Duplicate \"unix\" section");
161 hasSeenUnix = true;
162
163 processSectionUnix(item->second, isDryRun);
164 }
165 else if (item->first == "tcp")
166 {
167 if (hasSeenTcp)
168 throw Error("Duplicate \"tcp\" section");
169 hasSeenTcp = true;
170
171 processSectionTcp(item->second, isDryRun);
172 }
173 else if (item->first == "udp")
174 {
175 if (hasSeenUdp)
176 throw Error("Duplicate \"udp\" section");
177 hasSeenUdp = true;
178
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600179 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700180 }
181 else if (item->first == "ether")
182 {
183 if (hasSeenEther)
184 throw Error("Duplicate \"ether\" section");
185 hasSeenEther = true;
186
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600187 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700188 }
Wentao Shang53df1632014-04-21 12:01:32 -0700189 else if (item->first == "websocket")
190 {
191 if (hasSeenWebSocket)
192 throw Error("Duplicate \"websocket\" section");
193 hasSeenWebSocket = true;
194
195 processSectionWebSocket(item->second, isDryRun);
196 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700197 else
198 {
199 throw Error("Unrecognized option \"" + item->first + "\"");
200 }
201 }
202}
203
204void
205FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
206{
207 // ; the unix section contains settings of UNIX stream faces and channels
208 // unix
209 // {
210 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
211 // path /var/run/nfd.sock ; UNIX stream listener path
212 // }
213
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600214#if defined(HAVE_UNIX_SOCKETS)
215
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700216 bool needToListen = true;
217 std::string path = "/var/run/nfd.sock";
218
219 for (ConfigSection::const_iterator i = configSection.begin();
220 i != configSection.end();
221 ++i)
222 {
223 if (i->first == "path")
224 {
225 path = i->second.get_value<std::string>();
226 }
227 else if (i->first == "listen")
228 {
229 needToListen = parseYesNo(i, i->first, "unix");
230 }
231 else
232 {
233 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
234 }
235 }
236
237 if (!isDryRun)
238 {
239 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
240 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
241
242 if (needToListen)
243 {
244 // Should acceptFailed callback be used somehow?
245 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
246 UnixStreamChannel::ConnectFailedCallback());
247 }
248
249 m_factories.insert(std::make_pair("unix", factory));
250 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600251#else
252 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
253#endif // HAVE_UNIX_SOCKETS
254
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700255}
256
257void
258FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
259{
260 // ; the tcp section contains settings of TCP faces and channels
261 // tcp
262 // {
263 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
264 // port 6363 ; TCP listener port number
265 // }
266
267 std::string port = "6363";
268 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600269 bool enableV4 = true;
270 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700271
272 for (ConfigSection::const_iterator i = configSection.begin();
273 i != configSection.end();
274 ++i)
275 {
276 if (i->first == "port")
277 {
278 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600279 try
280 {
281 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
282 NFD_LOG_TRACE("TCP port set to " << portNo);
283 }
284 catch (const std::bad_cast& error)
285 {
286 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600287 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600288 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700289 }
290 else if (i->first == "listen")
291 {
292 needToListen = parseYesNo(i, i->first, "tcp");
293 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600294 else if (i->first == "enable_v4")
295 {
296 enableV4 = parseYesNo(i, i->first, "tcp");
297 }
298 else if (i->first == "enable_v6")
299 {
300 enableV6 = parseYesNo(i, i->first, "tcp");
301 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700302 else
303 {
304 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
305 }
306 }
307
Steve DiBenedetto95152872014-04-11 12:40:59 -0600308 if (!enableV4 && !enableV6)
309 {
310 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
311 " Remove \"tcp\" section to disable TCP channels or"
312 " re-enable at least one channel type.");
313 }
314
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700315 if (!isDryRun)
316 {
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700317 shared_ptr<TcpFactory> factory = ndn::make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600318 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700319
Steve DiBenedetto95152872014-04-11 12:40:59 -0600320 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700321 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600322 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
323 if (needToListen)
324 {
325 // Should acceptFailed callback be used somehow?
326 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
327 TcpChannel::ConnectFailedCallback());
328 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700329
Steve DiBenedetto95152872014-04-11 12:40:59 -0600330 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700331 }
332
Steve DiBenedetto95152872014-04-11 12:40:59 -0600333 if (enableV6)
334 {
335 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
336 if (needToListen)
337 {
338 // Should acceptFailed callback be used somehow?
339 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
340 TcpChannel::ConnectFailedCallback());
341 }
342
343 m_factories.insert(std::make_pair("tcp6", factory));
344 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700345 }
346}
347
348void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600349FaceManager::processSectionUdp(const ConfigSection& configSection,
350 bool isDryRun,
351 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700352{
353 // ; the udp section contains settings of UDP faces and channels
354 // udp
355 // {
356 // port 6363 ; UDP unicast port number
357 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
358 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
359
360 // ; NFD creates one UDP multicast face per NIC
361 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
362 // mcast_port 56363 ; UDP multicast port number
363 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
364 // }
365
366 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600367 bool enableV4 = true;
368 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700369 size_t timeout = 30;
370 size_t keepAliveInterval = 25;
371 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600372 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700373 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600374
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700375
376 for (ConfigSection::const_iterator i = configSection.begin();
377 i != configSection.end();
378 ++i)
379 {
380 if (i->first == "port")
381 {
382 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600383 try
384 {
385 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
386 NFD_LOG_TRACE("UDP port set to " << portNo);
387 }
388 catch (const std::bad_cast& error)
389 {
390 throw ConfigFile::Error("Invalid value for option " +
391 i->first + "\" in \"udp\" section");
392 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700393 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600394 else if (i->first == "enable_v4")
395 {
396 enableV4 = parseYesNo(i, i->first, "udp");
397 }
398 else if (i->first == "enable_v6")
399 {
400 enableV6 = parseYesNo(i, i->first, "udp");
401 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700402 else if (i->first == "idle_timeout")
403 {
404 try
405 {
406 timeout = i->second.get_value<size_t>();
407 }
408 catch (const std::exception& e)
409 {
410 throw ConfigFile::Error("Invalid value for option \"" +
411 i->first + "\" in \"udp\" section");
412 }
413 }
414 else if (i->first == "keep_alive_interval")
415 {
416 try
417 {
418 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700419
420 /// \todo Make use of keepAliveInterval
421 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700422 }
423 catch (const std::exception& e)
424 {
425 throw ConfigFile::Error("Invalid value for option \"" +
426 i->first + "\" in \"udp\" section");
427 }
428 }
429 else if (i->first == "mcast")
430 {
431 useMcast = parseYesNo(i, i->first, "udp");
432 }
433 else if (i->first == "mcast_port")
434 {
435 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600436 try
437 {
438 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
439 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
440 }
441 catch (const std::bad_cast& error)
442 {
443 throw ConfigFile::Error("Invalid value for option " +
444 i->first + "\" in \"udp\" section");
445 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700446 }
447 else if (i->first == "mcast_group")
448 {
449 using namespace boost::asio::ip;
450 mcastGroup = i->second.get_value<std::string>();
451 try
452 {
453 address mcastGroupTest = address::from_string(mcastGroup);
454 if (!mcastGroupTest.is_v4())
455 {
456 throw ConfigFile::Error("Invalid value for option \"" +
457 i->first + "\" in \"udp\" section");
458 }
459 }
460 catch(const std::runtime_error& e)
461 {
462 throw ConfigFile::Error("Invalid value for option \"" +
463 i->first + "\" in \"udp\" section");
464 }
465 }
466 else
467 {
468 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
469 }
470 }
471
Steve DiBenedetto95152872014-04-11 12:40:59 -0600472 if (!enableV4 && !enableV6)
473 {
474 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
475 " Remove \"udp\" section to disable UDP channels or"
476 " re-enable at least one channel type.");
477 }
478 else if (useMcast && !enableV4)
479 {
480 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
481 " have been disabled (conflicting configuration options set)");
482 }
483
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700484 /// \todo what is keep alive interval used for?
485
486 if (!isDryRun)
487 {
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700488 shared_ptr<UdpFactory> factory = ndn::make_shared<UdpFactory>(port);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700489 m_factories.insert(std::make_pair("udp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700490
Steve DiBenedetto95152872014-04-11 12:40:59 -0600491 if (enableV4)
492 {
493 shared_ptr<UdpChannel> v4Channel =
494 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
495
496 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
497 UdpChannel::ConnectFailedCallback());
498
499 m_factories.insert(std::make_pair("udp4", factory));
500 }
501
502 if (enableV6)
503 {
504 shared_ptr<UdpChannel> v6Channel =
505 factory->createChannel("::", port, time::seconds(timeout));
506
507 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
508 UdpChannel::ConnectFailedCallback());
509 m_factories.insert(std::make_pair("udp6", factory));
510 }
511
512 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700513 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200514 std::list<shared_ptr<NetworkInterfaceInfo> > ipv4MulticastInterfaces;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600515 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
516 i != nicList.end();
517 ++i)
518 {
519 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
520 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
521 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200522 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600523 }
524 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200525
526 bool isNicNameNecessary = false;
527
528#if defined(__linux__)
529 if (ipv4MulticastInterfaces.size() > 1)
530 {
531 //On Linux, if we have more than one MulticastUdpFace we need to specify
532 //the name of the interface
533 isNicNameNecessary = true;
534 }
535#endif
536
537 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i =
538 ipv4MulticastInterfaces.begin();
539 i != ipv4MulticastInterfaces.end();
540 ++i)
541 {
542 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
543 shared_ptr<MulticastUdpFace> newFace;
544 newFace = factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
545 mcastGroup,
546 mcastPort,
547 isNicNameNecessary ? nic->name : "");
548
549 addCreatedFaceToForwarder(newFace);
550 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600551 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700552 }
553}
554
555void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600556FaceManager::processSectionEther(const ConfigSection& configSection,
557 bool isDryRun,
558 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700559{
560 // ; the ether section contains settings of Ethernet faces and channels
561 // ether
562 // {
563 // ; NFD creates one Ethernet multicast face per NIC
564 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
565 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
566 // }
567
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700568#if defined(HAVE_LIBPCAP)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600569
570 using ethernet::Address;
571
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700572 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600573 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700574
575 for (ConfigSection::const_iterator i = configSection.begin();
576 i != configSection.end();
577 ++i)
578 {
579 if (i->first == "mcast")
580 {
581 useMcast = parseYesNo(i, i->first, "ether");
582 }
583
584 else if (i->first == "mcast_group")
585 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600586 mcastGroup = Address::fromString(i->second.get_value<std::string>());
587 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700588 {
589 throw ConfigFile::Error("Invalid value for option \"" +
590 i->first + "\" in \"ether\" section");
591 }
592 }
593 else
594 {
595 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
596 }
597 }
598
599 if (!isDryRun)
600 {
601 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
602 m_factories.insert(std::make_pair("ether", factory));
603
604 if (useMcast)
605 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600606 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
607 i != nicList.end();
608 ++i)
609 {
610 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
611 if (nic->isUp() && nic->isMulticastCapable())
612 {
613 try
614 {
615 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100616 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700617
618 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600619 }
620 catch (const EthernetFactory::Error& factoryError)
621 {
622 NFD_LOG_ERROR(factoryError.what() << ", continuing");
623 }
624 catch (const EthernetFace::Error& faceError)
625 {
626 NFD_LOG_ERROR(faceError.what() << ", continuing");
627 }
628 }
629 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700630 }
631 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600632#else
633 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700634#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700635}
636
Wentao Shang53df1632014-04-21 12:01:32 -0700637void
638FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
639{
640 // ; the websocket section contains settings of WebSocket faces and channels
641 // websocket
642 // {
643 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
644 // port 9696 ; WebSocket listener port number
645 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
646 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
647 // }
648
649#if defined(HAVE_WEBSOCKET)
650
651 std::string port = "9696";
652 bool needToListen = true;
653 bool enableV4 = true;
654 bool enableV6 = true;
655
656 for (ConfigSection::const_iterator i = configSection.begin();
657 i != configSection.end();
658 ++i)
659 {
660 if (i->first == "port")
661 {
662 port = i->second.get_value<std::string>();
663 try
664 {
665 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
666 NFD_LOG_TRACE("WebSocket port set to " << portNo);
667 }
668 catch (const std::bad_cast& error)
669 {
670 throw ConfigFile::Error("Invalid value for option " +
671 i->first + "\" in \"websocket\" section");
672 }
673 }
674 else if (i->first == "listen")
675 {
676 needToListen = parseYesNo(i, i->first, "websocket");
677 }
678 else if (i->first == "enable_v4")
679 {
680 enableV4 = parseYesNo(i, i->first, "websocket");
681 }
682 else if (i->first == "enable_v6")
683 {
684 enableV6 = parseYesNo(i, i->first, "websocket");
685 }
686 else
687 {
688 throw ConfigFile::Error("Unrecognized option \"" +
689 i->first + "\" in \"websocket\" section");
690 }
691 }
692
693 if (!enableV4 && !enableV6)
694 {
695 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
696 " Remove \"websocket\" section to disable WebSocket channels or"
697 " re-enable at least one channel type.");
698 }
699
700 if (!enableV4 && enableV6)
701 {
702 throw ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel.");
703 }
704
705 if (!isDryRun)
706 {
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700707 shared_ptr<WebSocketFactory> factory = ndn::make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700708 m_factories.insert(std::make_pair("websocket", factory));
709 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
710
711 if (enableV6 && enableV4)
712 {
713 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", portNo);
714 if (needToListen)
715 {
716 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
717 }
718
719 m_factories.insert(std::make_pair("websocket46", factory));
720 }
721 else if (enableV4)
722 {
723 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", portNo);
724 if (needToListen)
725 {
726 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
727 }
728
729 m_factories.insert(std::make_pair("websocket4", factory));
730 }
731 }
732#else
733 throw ConfigFile::Error("NFD was compiled without WebSocket, "
734 "cannot process \"websocket\" section");
735#endif // HAVE_WEBSOCKET
736}
737
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700738
739void
740FaceManager::onFaceRequest(const Interest& request)
741{
742 const Name& command = request.getName();
743 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600744 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700745
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600746 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
747 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
748 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700749 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700750 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600751 }
752 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600753 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700754 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700755 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700756 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700757 }
758 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
759 !COMMAND_PREFIX.isPrefixOf(command))
760 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700761 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700762 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700763 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600764 else
765 {
766 validate(request,
767 bind(&FaceManager::onValidatedFaceRequest, this, _1),
768 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
769 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700770}
771
772void
773FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
774{
775 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600776 const Name::Component& verb = command[COMMAND_PREFIX.size()];
777 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700778
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600779 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
780 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700781 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600782 ControlParameters parameters;
783 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700784 {
785 sendResponse(command, 400, "Malformed command");
786 return;
787 }
788
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700789 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600790 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700791 }
792 else
793 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700794 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700795 sendResponse(command, 501, "Unsupported command");
796 }
797
798}
799
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700800void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700801FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
802{
803 m_faceTable.add(newFace);
804
Junxiao Shi6e694322014-04-03 10:27:13 -0700805 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700806}
807
808void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700809FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600810 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700811 const shared_ptr<Face>& newFace)
812{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700813 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600814 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700815
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600816 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700817}
818
819void
820FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
821{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700822 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600823 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700824}
825
826void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600827FaceManager::createFace(const Interest& request,
828 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700829{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600830 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600831 ndn::nfd::FaceCreateCommand command;
832
833 if (!validateParameters(command, parameters))
834 {
835 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600836 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600837 return;
838 }
839
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700840 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600841 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700842 {
843 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600844 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700845 return;
846 }
847
848 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
849 if (factory == m_factories.end())
850 {
851 sendResponse(requestName, 501, "Unsupported protocol");
852 return;
853 }
854
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600855 try
856 {
857 factory->second->createFace(uri,
858 bind(&FaceManager::onCreated,
859 this, requestName, parameters, _1),
860 bind(&FaceManager::onConnectFailed,
861 this, requestName, _1));
862 }
863 catch (const std::runtime_error& error)
864 {
865 std::string errorMessage = "NFD error: ";
866 errorMessage += error.what();
867
868 NFD_LOG_ERROR(errorMessage);
869 sendResponse(requestName, 500, errorMessage);
870 }
871 catch (const std::logic_error& error)
872 {
873 std::string errorMessage = "NFD error: ";
874 errorMessage += error.what();
875
876 NFD_LOG_ERROR(errorMessage);
877 sendResponse(requestName, 500, errorMessage);
878 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700879}
880
881
882void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600883FaceManager::destroyFace(const Interest& request,
884 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700885{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600886 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600887 ndn::nfd::FaceDestroyCommand command;
888
889 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600890 {
891 sendResponse(requestName, 400, "Malformed command");
892 return;
893 }
894
895 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600896 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700897 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700898 target->close();
899 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600900
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600901 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600902
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700903}
904
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600905void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600906FaceManager::onAddFace(shared_ptr<Face> face)
907{
Junxiao Shi6e694322014-04-03 10:27:13 -0700908 ndn::nfd::FaceEventNotification notification;
909 notification.setKind(ndn::nfd::FACE_EVENT_CREATED)
910 .setFaceId(face->getId())
911 .setRemoteUri(face->getRemoteUri().toString())
912 .setLocalUri(face->getLocalUri().toString())
913 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600914
Junxiao Shi6e694322014-04-03 10:27:13 -0700915 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600916}
917
918void
919FaceManager::onRemoveFace(shared_ptr<Face> face)
920{
Junxiao Shi6e694322014-04-03 10:27:13 -0700921 ndn::nfd::FaceEventNotification notification;
922 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
923 .setFaceId(face->getId())
924 .setRemoteUri(face->getRemoteUri().toString())
925 .setLocalUri(face->getLocalUri().toString())
926 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600927
Junxiao Shi6e694322014-04-03 10:27:13 -0700928 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600929}
930
931
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600932bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600933FaceManager::extractLocalControlParameters(const Interest& request,
934 ControlParameters& parameters,
935 ControlCommand& command,
936 shared_ptr<LocalFace>& outFace,
937 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600938{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600939 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600940 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600941 sendResponse(request.getName(), 400, "Malformed command");
942 return false;
943 }
944
945 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
946
947 if (!static_cast<bool>(face))
948 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700949 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600950 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600951 return false;
952 }
953 else if (!face->isLocal())
954 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700955 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
956 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600957 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600958 return false;
959 }
960
961 outFace = dynamic_pointer_cast<LocalFace>(face);
962 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
963
964 return true;
965}
966
967void
968FaceManager::enableLocalControl(const Interest& request,
969 ControlParameters& parameters)
970{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600971 ndn::nfd::FaceEnableLocalControlCommand command;
972
973
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600974 shared_ptr<LocalFace> face;
975 LocalControlFeature feature;
976
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600977 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600978 {
979 face->setLocalControlHeaderFeature(feature, true);
980 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
981 }
982}
983
984void
985FaceManager::disableLocalControl(const Interest& request,
986 ControlParameters& parameters)
987{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600988 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600989 shared_ptr<LocalFace> face;
990 LocalControlFeature feature;
991
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600992 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600993 {
994 face->setLocalControlHeaderFeature(feature, false);
995 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
996 }
997}
998
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600999void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001000FaceManager::listFaces(const Interest& request)
1001{
1002 const Name& command = request.getName();
1003 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001004
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001005 if (commandNComps < LIST_COMMAND_NCOMPS ||
1006 !LIST_COMMAND_PREFIX.isPrefixOf(command))
1007 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001008 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001009 sendResponse(command, 400, "Malformed command");
1010 return;
1011 }
1012
1013 m_statusPublisher.publish();
1014}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001015
1016} // namespace nfd