blob: 95b01e042cc5bb3c2b80f36a800e6a6e07b3828a [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"
Davide Pesavento52a18f92014-04-10 00:55:01 +020034#include "mgmt/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
40#ifdef HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041#include "face/ethernet-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060042#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043
Davide Pesavento52a18f92014-04-10 00:55:01 +020044#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
45
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070046namespace nfd {
47
48NFD_LOG_INIT("FaceManager");
49
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060050const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070051
52const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
53 FaceManager::COMMAND_PREFIX.size() +
54 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060055 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070056
57const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
58 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070059 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070060
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060061const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070062 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060063 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060064 Name::Component("create"),
65 &FaceManager::createFace
66 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070067
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060068 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060069 Name::Component("destroy"),
70 &FaceManager::destroyFace
71 ),
72
73 SignedVerbAndProcessor(
74 Name::Component("enable-local-control"),
75 &FaceManager::enableLocalControl
76 ),
77
78 SignedVerbAndProcessor(
79 Name::Component("disable-local-control"),
80 &FaceManager::disableLocalControl
81 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070082 };
83
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060084const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
85 {
86 UnsignedVerbAndProcessor(
87 Name::Component("list"),
88 &FaceManager::listFaces
89 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060090
91 UnsignedVerbAndProcessor(
92 Name::Component("events"),
93 &FaceManager::ignoreUnsignedVerb
94 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060095 };
96
97const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
98const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
99
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600100const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700101
102FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700103 shared_ptr<InternalFace> face)
104 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700105 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600106 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600107 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600108 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600109 SIGNED_COMMAND_VERBS +
110 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600111 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600112 UNSIGNED_COMMAND_VERBS +
113 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600114
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700115{
116 face->setInterestFilter("/localhost/nfd/faces",
117 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600118
119 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
120 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700121}
122
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600123FaceManager::~FaceManager()
124{
125
126}
127
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700128void
129FaceManager::setConfigFile(ConfigFile& configFile)
130{
131 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600132 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700133}
134
135
136void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600137FaceManager::onConfig(const ConfigSection& configSection,
138 bool isDryRun,
139 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700140{
141 bool hasSeenUnix = false;
142 bool hasSeenTcp = false;
143 bool hasSeenUdp = false;
144 bool hasSeenEther = false;
145
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600146 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
147
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700148 for (ConfigSection::const_iterator item = configSection.begin();
149 item != configSection.end();
150 ++item)
151 {
152 if (item->first == "unix")
153 {
154 if (hasSeenUnix)
155 throw Error("Duplicate \"unix\" section");
156 hasSeenUnix = true;
157
158 processSectionUnix(item->second, isDryRun);
159 }
160 else if (item->first == "tcp")
161 {
162 if (hasSeenTcp)
163 throw Error("Duplicate \"tcp\" section");
164 hasSeenTcp = true;
165
166 processSectionTcp(item->second, isDryRun);
167 }
168 else if (item->first == "udp")
169 {
170 if (hasSeenUdp)
171 throw Error("Duplicate \"udp\" section");
172 hasSeenUdp = true;
173
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600174 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700175 }
176 else if (item->first == "ether")
177 {
178 if (hasSeenEther)
179 throw Error("Duplicate \"ether\" section");
180 hasSeenEther = true;
181
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600182 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700183 }
184 else
185 {
186 throw Error("Unrecognized option \"" + item->first + "\"");
187 }
188 }
189}
190
191void
192FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
193{
194 // ; the unix section contains settings of UNIX stream faces and channels
195 // unix
196 // {
197 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
198 // path /var/run/nfd.sock ; UNIX stream listener path
199 // }
200
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600201#if defined(HAVE_UNIX_SOCKETS)
202
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700203 bool needToListen = true;
204 std::string path = "/var/run/nfd.sock";
205
206 for (ConfigSection::const_iterator i = configSection.begin();
207 i != configSection.end();
208 ++i)
209 {
210 if (i->first == "path")
211 {
212 path = i->second.get_value<std::string>();
213 }
214 else if (i->first == "listen")
215 {
216 needToListen = parseYesNo(i, i->first, "unix");
217 }
218 else
219 {
220 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
221 }
222 }
223
224 if (!isDryRun)
225 {
226 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
227 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
228
229 if (needToListen)
230 {
231 // Should acceptFailed callback be used somehow?
232 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
233 UnixStreamChannel::ConnectFailedCallback());
234 }
235
236 m_factories.insert(std::make_pair("unix", factory));
237 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600238#else
239 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
240#endif // HAVE_UNIX_SOCKETS
241
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700242}
243
244void
245FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
246{
247 // ; the tcp section contains settings of TCP faces and channels
248 // tcp
249 // {
250 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
251 // port 6363 ; TCP listener port number
252 // }
253
254 std::string port = "6363";
255 bool needToListen = true;
256
257 for (ConfigSection::const_iterator i = configSection.begin();
258 i != configSection.end();
259 ++i)
260 {
261 if (i->first == "port")
262 {
263 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600264 try
265 {
266 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
267 NFD_LOG_TRACE("TCP port set to " << portNo);
268 }
269 catch (const std::bad_cast& error)
270 {
271 throw ConfigFile::Error("Invalid value for option " +
272 i->first + "\" in \"udp\" section");
273 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700274 }
275 else if (i->first == "listen")
276 {
277 needToListen = parseYesNo(i, i->first, "tcp");
278 }
279 else
280 {
281 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
282 }
283 }
284
285 if (!isDryRun)
286 {
287 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
288
289 using namespace boost::asio::ip;
290
291 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
292 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
293
294 if (needToListen)
295 {
296 // Should acceptFailed callback be used somehow?
297
298 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
299 TcpChannel::ConnectFailedCallback());
300 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
301 TcpChannel::ConnectFailedCallback());
302 }
303
304 m_factories.insert(std::make_pair("tcp", factory));
305 m_factories.insert(std::make_pair("tcp4", factory));
306 m_factories.insert(std::make_pair("tcp6", factory));
307 }
308}
309
310void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600311FaceManager::processSectionUdp(const ConfigSection& configSection,
312 bool isDryRun,
313 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700314{
315 // ; the udp section contains settings of UDP faces and channels
316 // udp
317 // {
318 // port 6363 ; UDP unicast port number
319 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
320 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
321
322 // ; NFD creates one UDP multicast face per NIC
323 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
324 // mcast_port 56363 ; UDP multicast port number
325 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
326 // }
327
328 std::string port = "6363";
329 size_t timeout = 30;
330 size_t keepAliveInterval = 25;
331 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600332 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700333 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600334
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700335
336 for (ConfigSection::const_iterator i = configSection.begin();
337 i != configSection.end();
338 ++i)
339 {
340 if (i->first == "port")
341 {
342 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600343 try
344 {
345 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
346 NFD_LOG_TRACE("UDP port set to " << portNo);
347 }
348 catch (const std::bad_cast& error)
349 {
350 throw ConfigFile::Error("Invalid value for option " +
351 i->first + "\" in \"udp\" section");
352 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700353 }
354 else if (i->first == "idle_timeout")
355 {
356 try
357 {
358 timeout = i->second.get_value<size_t>();
359 }
360 catch (const std::exception& e)
361 {
362 throw ConfigFile::Error("Invalid value for option \"" +
363 i->first + "\" in \"udp\" section");
364 }
365 }
366 else if (i->first == "keep_alive_interval")
367 {
368 try
369 {
370 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700371
372 /// \todo Make use of keepAliveInterval
373 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700374 }
375 catch (const std::exception& e)
376 {
377 throw ConfigFile::Error("Invalid value for option \"" +
378 i->first + "\" in \"udp\" section");
379 }
380 }
381 else if (i->first == "mcast")
382 {
383 useMcast = parseYesNo(i, i->first, "udp");
384 }
385 else if (i->first == "mcast_port")
386 {
387 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600388 try
389 {
390 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
391 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
392 }
393 catch (const std::bad_cast& error)
394 {
395 throw ConfigFile::Error("Invalid value for option " +
396 i->first + "\" in \"udp\" section");
397 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700398 }
399 else if (i->first == "mcast_group")
400 {
401 using namespace boost::asio::ip;
402 mcastGroup = i->second.get_value<std::string>();
403 try
404 {
405 address mcastGroupTest = address::from_string(mcastGroup);
406 if (!mcastGroupTest.is_v4())
407 {
408 throw ConfigFile::Error("Invalid value for option \"" +
409 i->first + "\" in \"udp\" section");
410 }
411 }
412 catch(const std::runtime_error& e)
413 {
414 throw ConfigFile::Error("Invalid value for option \"" +
415 i->first + "\" in \"udp\" section");
416 }
417 }
418 else
419 {
420 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
421 }
422 }
423
424 /// \todo what is keep alive interval used for?
425
426 if (!isDryRun)
427 {
428 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
429
Steve DiBenedettob9906cf2014-03-27 09:18:28 -0600430 shared_ptr<UdpChannel> v4Channel =
431 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
432
433 shared_ptr<UdpChannel> v6Channel =
434 factory->createChannel("::", port, time::seconds(timeout));
435
436 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
437 UdpChannel::ConnectFailedCallback());
438
439 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
440 UdpChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700441
442 m_factories.insert(std::make_pair("udp", factory));
443 m_factories.insert(std::make_pair("udp4", factory));
444 m_factories.insert(std::make_pair("udp6", factory));
445
446 if (useMcast)
447 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600448 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
449 i != nicList.end();
450 ++i)
451 {
452 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
453 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
454 {
455 shared_ptr<MulticastUdpFace> newFace =
456 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
457 mcastGroup, mcastPort);
458
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700459 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600460 }
461 }
462 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700463 }
464}
465
466void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600467FaceManager::processSectionEther(const ConfigSection& configSection,
468 bool isDryRun,
469 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700470{
471 // ; the ether section contains settings of Ethernet faces and channels
472 // ether
473 // {
474 // ; NFD creates one Ethernet multicast face per NIC
475 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
476 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
477 // }
478
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600479#if defined(HAVE_PCAP)
480
481 using ethernet::Address;
482
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700483 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600484 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700485
486 for (ConfigSection::const_iterator i = configSection.begin();
487 i != configSection.end();
488 ++i)
489 {
490 if (i->first == "mcast")
491 {
492 useMcast = parseYesNo(i, i->first, "ether");
493 }
494
495 else if (i->first == "mcast_group")
496 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600497 mcastGroup = Address::fromString(i->second.get_value<std::string>());
498 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700499 {
500 throw ConfigFile::Error("Invalid value for option \"" +
501 i->first + "\" in \"ether\" section");
502 }
503 }
504 else
505 {
506 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
507 }
508 }
509
510 if (!isDryRun)
511 {
512 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
513 m_factories.insert(std::make_pair("ether", factory));
514
515 if (useMcast)
516 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600517 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
518 i != nicList.end();
519 ++i)
520 {
521 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
522 if (nic->isUp() && nic->isMulticastCapable())
523 {
524 try
525 {
526 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100527 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700528
529 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600530 }
531 catch (const EthernetFactory::Error& factoryError)
532 {
533 NFD_LOG_ERROR(factoryError.what() << ", continuing");
534 }
535 catch (const EthernetFace::Error& faceError)
536 {
537 NFD_LOG_ERROR(faceError.what() << ", continuing");
538 }
539 }
540 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700541 }
542 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600543#else
544 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
545#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700546}
547
548
549void
550FaceManager::onFaceRequest(const Interest& request)
551{
552 const Name& command = request.getName();
553 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600554 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700555
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600556 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
557 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
558 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700559 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600560 (unsignedVerbProcessor->second)(this, boost::cref(request));
561 }
562 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600563 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700564 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700565 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700566 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700567 }
568 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
569 !COMMAND_PREFIX.isPrefixOf(command))
570 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700571 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700572 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700573 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600574 else
575 {
576 validate(request,
577 bind(&FaceManager::onValidatedFaceRequest, this, _1),
578 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
579 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700580}
581
582void
583FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
584{
585 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600586 const Name::Component& verb = command[COMMAND_PREFIX.size()];
587 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700588
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600589 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
590 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700591 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600592 ControlParameters parameters;
593 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700594 {
595 sendResponse(command, 400, "Malformed command");
596 return;
597 }
598
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700599 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600600 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700601 }
602 else
603 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700604 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700605 sendResponse(command, 501, "Unsupported command");
606 }
607
608}
609
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700610void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700611FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
612{
613 m_faceTable.add(newFace);
614
Junxiao Shi6e694322014-04-03 10:27:13 -0700615 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700616}
617
618void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700619FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600620 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700621 const shared_ptr<Face>& newFace)
622{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700623 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600624 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700625
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600626 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700627}
628
629void
630FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
631{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700632 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600633 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700634}
635
636void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600637FaceManager::createFace(const Interest& request,
638 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700639{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600640 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600641 ndn::nfd::FaceCreateCommand command;
642
643 if (!validateParameters(command, parameters))
644 {
645 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600646 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600647 return;
648 }
649
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700650 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600651 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700652 {
653 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600654 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700655 return;
656 }
657
658 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
659 if (factory == m_factories.end())
660 {
661 sendResponse(requestName, 501, "Unsupported protocol");
662 return;
663 }
664
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600665 try
666 {
667 factory->second->createFace(uri,
668 bind(&FaceManager::onCreated,
669 this, requestName, parameters, _1),
670 bind(&FaceManager::onConnectFailed,
671 this, requestName, _1));
672 }
673 catch (const std::runtime_error& error)
674 {
675 std::string errorMessage = "NFD error: ";
676 errorMessage += error.what();
677
678 NFD_LOG_ERROR(errorMessage);
679 sendResponse(requestName, 500, errorMessage);
680 }
681 catch (const std::logic_error& error)
682 {
683 std::string errorMessage = "NFD error: ";
684 errorMessage += error.what();
685
686 NFD_LOG_ERROR(errorMessage);
687 sendResponse(requestName, 500, errorMessage);
688 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700689}
690
691
692void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600693FaceManager::destroyFace(const Interest& request,
694 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700695{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600696 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600697 ndn::nfd::FaceDestroyCommand command;
698
699 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600700 {
701 sendResponse(requestName, 400, "Malformed command");
702 return;
703 }
704
705 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600706 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700707 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700708 target->close();
709 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600710
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600711 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600712
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700713}
714
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600715void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600716FaceManager::onAddFace(shared_ptr<Face> face)
717{
Junxiao Shi6e694322014-04-03 10:27:13 -0700718 ndn::nfd::FaceEventNotification notification;
719 notification.setKind(ndn::nfd::FACE_EVENT_CREATED)
720 .setFaceId(face->getId())
721 .setRemoteUri(face->getRemoteUri().toString())
722 .setLocalUri(face->getLocalUri().toString())
723 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600724
Junxiao Shi6e694322014-04-03 10:27:13 -0700725 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600726}
727
728void
729FaceManager::onRemoveFace(shared_ptr<Face> face)
730{
Junxiao Shi6e694322014-04-03 10:27:13 -0700731 ndn::nfd::FaceEventNotification notification;
732 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
733 .setFaceId(face->getId())
734 .setRemoteUri(face->getRemoteUri().toString())
735 .setLocalUri(face->getLocalUri().toString())
736 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600737
Junxiao Shi6e694322014-04-03 10:27:13 -0700738 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600739}
740
741
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600742bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600743FaceManager::extractLocalControlParameters(const Interest& request,
744 ControlParameters& parameters,
745 ControlCommand& command,
746 shared_ptr<LocalFace>& outFace,
747 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600748{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600749 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600750 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600751 sendResponse(request.getName(), 400, "Malformed command");
752 return false;
753 }
754
755 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
756
757 if (!static_cast<bool>(face))
758 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700759 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600760 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600761 return false;
762 }
763 else if (!face->isLocal())
764 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700765 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
766 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600767 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600768 return false;
769 }
770
771 outFace = dynamic_pointer_cast<LocalFace>(face);
772 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
773
774 return true;
775}
776
777void
778FaceManager::enableLocalControl(const Interest& request,
779 ControlParameters& parameters)
780{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600781 ndn::nfd::FaceEnableLocalControlCommand command;
782
783
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600784 shared_ptr<LocalFace> face;
785 LocalControlFeature feature;
786
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600787 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600788 {
789 face->setLocalControlHeaderFeature(feature, true);
790 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
791 }
792}
793
794void
795FaceManager::disableLocalControl(const Interest& request,
796 ControlParameters& parameters)
797{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600798 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600799 shared_ptr<LocalFace> face;
800 LocalControlFeature feature;
801
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600802 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600803 {
804 face->setLocalControlHeaderFeature(feature, false);
805 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
806 }
807}
808
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600809void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600810FaceManager::listFaces(const Interest& request)
811{
812 const Name& command = request.getName();
813 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700814
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600815 if (commandNComps < LIST_COMMAND_NCOMPS ||
816 !LIST_COMMAND_PREFIX.isPrefixOf(command))
817 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700818 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600819 sendResponse(command, 400, "Malformed command");
820 return;
821 }
822
823 m_statusPublisher.publish();
824}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700825
826} // namespace nfd