blob: 29f2b9ef625875b7dcbeddc9d7bd4534bef08648 [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"
Junxiao Shi6e694322014-04-03 10:27:13 -070026#include "face-flags.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070027
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"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060034
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060035#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
36
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060037#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070038#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060039#endif // HAVE_UNIX_SOCKETS
40
41#ifdef HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070042#include "face/ethernet-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060043#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070044
45namespace nfd {
46
47NFD_LOG_INIT("FaceManager");
48
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060049const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070050
51const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
52 FaceManager::COMMAND_PREFIX.size() +
53 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060054 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070055
56const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
57 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070058 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070059
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060060const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070061 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060062 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060063 Name::Component("create"),
64 &FaceManager::createFace
65 ),
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("destroy"),
69 &FaceManager::destroyFace
70 ),
71
72 SignedVerbAndProcessor(
73 Name::Component("enable-local-control"),
74 &FaceManager::enableLocalControl
75 ),
76
77 SignedVerbAndProcessor(
78 Name::Component("disable-local-control"),
79 &FaceManager::disableLocalControl
80 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070081 };
82
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060083const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
84 {
85 UnsignedVerbAndProcessor(
86 Name::Component("list"),
87 &FaceManager::listFaces
88 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060089
90 UnsignedVerbAndProcessor(
91 Name::Component("events"),
92 &FaceManager::ignoreUnsignedVerb
93 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060094 };
95
96const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
97const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
98
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060099const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700100
101FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700102 shared_ptr<InternalFace> face)
103 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700104 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600105 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600106 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600107 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600108 SIGNED_COMMAND_VERBS +
109 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600110 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600111 UNSIGNED_COMMAND_VERBS +
112 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600113
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700114{
115 face->setInterestFilter("/localhost/nfd/faces",
116 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600117
118 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
119 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700120}
121
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600122FaceManager::~FaceManager()
123{
124
125}
126
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700127void
128FaceManager::setConfigFile(ConfigFile& configFile)
129{
130 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600131 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700132}
133
134
135void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600136FaceManager::onConfig(const ConfigSection& configSection,
137 bool isDryRun,
138 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700139{
140 bool hasSeenUnix = false;
141 bool hasSeenTcp = false;
142 bool hasSeenUdp = false;
143 bool hasSeenEther = false;
144
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600145 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
146
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700147 for (ConfigSection::const_iterator item = configSection.begin();
148 item != configSection.end();
149 ++item)
150 {
151 if (item->first == "unix")
152 {
153 if (hasSeenUnix)
154 throw Error("Duplicate \"unix\" section");
155 hasSeenUnix = true;
156
157 processSectionUnix(item->second, isDryRun);
158 }
159 else if (item->first == "tcp")
160 {
161 if (hasSeenTcp)
162 throw Error("Duplicate \"tcp\" section");
163 hasSeenTcp = true;
164
165 processSectionTcp(item->second, isDryRun);
166 }
167 else if (item->first == "udp")
168 {
169 if (hasSeenUdp)
170 throw Error("Duplicate \"udp\" section");
171 hasSeenUdp = true;
172
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600173 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700174 }
175 else if (item->first == "ether")
176 {
177 if (hasSeenEther)
178 throw Error("Duplicate \"ether\" section");
179 hasSeenEther = true;
180
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600181 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700182 }
183 else
184 {
185 throw Error("Unrecognized option \"" + item->first + "\"");
186 }
187 }
188}
189
190void
191FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
192{
193 // ; the unix section contains settings of UNIX stream faces and channels
194 // unix
195 // {
196 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
197 // path /var/run/nfd.sock ; UNIX stream listener path
198 // }
199
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600200#if defined(HAVE_UNIX_SOCKETS)
201
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700202 bool needToListen = true;
203 std::string path = "/var/run/nfd.sock";
204
205 for (ConfigSection::const_iterator i = configSection.begin();
206 i != configSection.end();
207 ++i)
208 {
209 if (i->first == "path")
210 {
211 path = i->second.get_value<std::string>();
212 }
213 else if (i->first == "listen")
214 {
215 needToListen = parseYesNo(i, i->first, "unix");
216 }
217 else
218 {
219 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
220 }
221 }
222
223 if (!isDryRun)
224 {
225 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
226 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
227
228 if (needToListen)
229 {
230 // Should acceptFailed callback be used somehow?
231 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
232 UnixStreamChannel::ConnectFailedCallback());
233 }
234
235 m_factories.insert(std::make_pair("unix", factory));
236 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600237#else
238 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
239#endif // HAVE_UNIX_SOCKETS
240
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700241}
242
243void
244FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
245{
246 // ; the tcp section contains settings of TCP faces and channels
247 // tcp
248 // {
249 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
250 // port 6363 ; TCP listener port number
251 // }
252
253 std::string port = "6363";
254 bool needToListen = true;
255
256 for (ConfigSection::const_iterator i = configSection.begin();
257 i != configSection.end();
258 ++i)
259 {
260 if (i->first == "port")
261 {
262 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600263 try
264 {
265 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
266 NFD_LOG_TRACE("TCP port set to " << portNo);
267 }
268 catch (const std::bad_cast& error)
269 {
270 throw ConfigFile::Error("Invalid value for option " +
271 i->first + "\" in \"udp\" section");
272 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700273 }
274 else if (i->first == "listen")
275 {
276 needToListen = parseYesNo(i, i->first, "tcp");
277 }
278 else
279 {
280 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
281 }
282 }
283
284 if (!isDryRun)
285 {
286 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
287
288 using namespace boost::asio::ip;
289
290 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
291 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
292
293 if (needToListen)
294 {
295 // Should acceptFailed callback be used somehow?
296
297 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
298 TcpChannel::ConnectFailedCallback());
299 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
300 TcpChannel::ConnectFailedCallback());
301 }
302
303 m_factories.insert(std::make_pair("tcp", factory));
304 m_factories.insert(std::make_pair("tcp4", factory));
305 m_factories.insert(std::make_pair("tcp6", factory));
306 }
307}
308
309void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600310FaceManager::processSectionUdp(const ConfigSection& configSection,
311 bool isDryRun,
312 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700313{
314 // ; the udp section contains settings of UDP faces and channels
315 // udp
316 // {
317 // port 6363 ; UDP unicast port number
318 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
319 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
320
321 // ; NFD creates one UDP multicast face per NIC
322 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
323 // mcast_port 56363 ; UDP multicast port number
324 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
325 // }
326
327 std::string port = "6363";
328 size_t timeout = 30;
329 size_t keepAliveInterval = 25;
330 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600331 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700332 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600333
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700334
335 for (ConfigSection::const_iterator i = configSection.begin();
336 i != configSection.end();
337 ++i)
338 {
339 if (i->first == "port")
340 {
341 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600342 try
343 {
344 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
345 NFD_LOG_TRACE("UDP port set to " << portNo);
346 }
347 catch (const std::bad_cast& error)
348 {
349 throw ConfigFile::Error("Invalid value for option " +
350 i->first + "\" in \"udp\" section");
351 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700352 }
353 else if (i->first == "idle_timeout")
354 {
355 try
356 {
357 timeout = i->second.get_value<size_t>();
358 }
359 catch (const std::exception& e)
360 {
361 throw ConfigFile::Error("Invalid value for option \"" +
362 i->first + "\" in \"udp\" section");
363 }
364 }
365 else if (i->first == "keep_alive_interval")
366 {
367 try
368 {
369 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700370
371 /// \todo Make use of keepAliveInterval
372 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700373 }
374 catch (const std::exception& e)
375 {
376 throw ConfigFile::Error("Invalid value for option \"" +
377 i->first + "\" in \"udp\" section");
378 }
379 }
380 else if (i->first == "mcast")
381 {
382 useMcast = parseYesNo(i, i->first, "udp");
383 }
384 else if (i->first == "mcast_port")
385 {
386 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600387 try
388 {
389 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
390 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
391 }
392 catch (const std::bad_cast& error)
393 {
394 throw ConfigFile::Error("Invalid value for option " +
395 i->first + "\" in \"udp\" section");
396 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700397 }
398 else if (i->first == "mcast_group")
399 {
400 using namespace boost::asio::ip;
401 mcastGroup = i->second.get_value<std::string>();
402 try
403 {
404 address mcastGroupTest = address::from_string(mcastGroup);
405 if (!mcastGroupTest.is_v4())
406 {
407 throw ConfigFile::Error("Invalid value for option \"" +
408 i->first + "\" in \"udp\" section");
409 }
410 }
411 catch(const std::runtime_error& e)
412 {
413 throw ConfigFile::Error("Invalid value for option \"" +
414 i->first + "\" in \"udp\" section");
415 }
416 }
417 else
418 {
419 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
420 }
421 }
422
423 /// \todo what is keep alive interval used for?
424
425 if (!isDryRun)
426 {
427 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
428
Steve DiBenedettob9906cf2014-03-27 09:18:28 -0600429 shared_ptr<UdpChannel> v4Channel =
430 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
431
432 shared_ptr<UdpChannel> v6Channel =
433 factory->createChannel("::", port, time::seconds(timeout));
434
435 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
436 UdpChannel::ConnectFailedCallback());
437
438 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
439 UdpChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700440
441 m_factories.insert(std::make_pair("udp", factory));
442 m_factories.insert(std::make_pair("udp4", factory));
443 m_factories.insert(std::make_pair("udp6", factory));
444
445 if (useMcast)
446 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600447 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
448 i != nicList.end();
449 ++i)
450 {
451 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
452 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
453 {
454 shared_ptr<MulticastUdpFace> newFace =
455 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
456 mcastGroup, mcastPort);
457
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700458 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600459 }
460 }
461 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700462 }
463}
464
465void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600466FaceManager::processSectionEther(const ConfigSection& configSection,
467 bool isDryRun,
468 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700469{
470 // ; the ether section contains settings of Ethernet faces and channels
471 // ether
472 // {
473 // ; NFD creates one Ethernet multicast face per NIC
474 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
475 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
476 // }
477
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600478#if defined(HAVE_PCAP)
479
480 using ethernet::Address;
481
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700482 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600483 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700484
485 for (ConfigSection::const_iterator i = configSection.begin();
486 i != configSection.end();
487 ++i)
488 {
489 if (i->first == "mcast")
490 {
491 useMcast = parseYesNo(i, i->first, "ether");
492 }
493
494 else if (i->first == "mcast_group")
495 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600496 mcastGroup = Address::fromString(i->second.get_value<std::string>());
497 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700498 {
499 throw ConfigFile::Error("Invalid value for option \"" +
500 i->first + "\" in \"ether\" section");
501 }
502 }
503 else
504 {
505 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
506 }
507 }
508
509 if (!isDryRun)
510 {
511 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
512 m_factories.insert(std::make_pair("ether", factory));
513
514 if (useMcast)
515 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600516 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
517 i != nicList.end();
518 ++i)
519 {
520 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
521 if (nic->isUp() && nic->isMulticastCapable())
522 {
523 try
524 {
525 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100526 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700527
528 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600529 }
530 catch (const EthernetFactory::Error& factoryError)
531 {
532 NFD_LOG_ERROR(factoryError.what() << ", continuing");
533 }
534 catch (const EthernetFace::Error& faceError)
535 {
536 NFD_LOG_ERROR(faceError.what() << ", continuing");
537 }
538 }
539 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700540 }
541 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600542#else
543 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
544#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700545}
546
547
548void
549FaceManager::onFaceRequest(const Interest& request)
550{
551 const Name& command = request.getName();
552 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600553 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700554
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600555 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
556 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
557 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700558 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600559 (unsignedVerbProcessor->second)(this, boost::cref(request));
560 }
561 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600562 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700563 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700564 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700565 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700566 }
567 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
568 !COMMAND_PREFIX.isPrefixOf(command))
569 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700570 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700571 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700572 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600573 else
574 {
575 validate(request,
576 bind(&FaceManager::onValidatedFaceRequest, this, _1),
577 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
578 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700579}
580
581void
582FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
583{
584 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600585 const Name::Component& verb = command[COMMAND_PREFIX.size()];
586 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700587
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600588 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
589 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700590 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600591 ControlParameters parameters;
592 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700593 {
594 sendResponse(command, 400, "Malformed command");
595 return;
596 }
597
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700598 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600599 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700600 }
601 else
602 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700603 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700604 sendResponse(command, 501, "Unsupported command");
605 }
606
607}
608
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700609void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700610FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
611{
612 m_faceTable.add(newFace);
613
Junxiao Shi6e694322014-04-03 10:27:13 -0700614 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700615}
616
617void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700618FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600619 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700620 const shared_ptr<Face>& newFace)
621{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700622 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600623 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700624
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600625 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700626}
627
628void
629FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
630{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700631 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600632 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700633}
634
635void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600636FaceManager::createFace(const Interest& request,
637 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700638{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600639 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600640 ndn::nfd::FaceCreateCommand command;
641
642 if (!validateParameters(command, parameters))
643 {
644 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600645 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600646 return;
647 }
648
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700649 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600650 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700651 {
652 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600653 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700654 return;
655 }
656
657 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
658 if (factory == m_factories.end())
659 {
660 sendResponse(requestName, 501, "Unsupported protocol");
661 return;
662 }
663
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600664 try
665 {
666 factory->second->createFace(uri,
667 bind(&FaceManager::onCreated,
668 this, requestName, parameters, _1),
669 bind(&FaceManager::onConnectFailed,
670 this, requestName, _1));
671 }
672 catch (const std::runtime_error& error)
673 {
674 std::string errorMessage = "NFD error: ";
675 errorMessage += error.what();
676
677 NFD_LOG_ERROR(errorMessage);
678 sendResponse(requestName, 500, errorMessage);
679 }
680 catch (const std::logic_error& error)
681 {
682 std::string errorMessage = "NFD error: ";
683 errorMessage += error.what();
684
685 NFD_LOG_ERROR(errorMessage);
686 sendResponse(requestName, 500, errorMessage);
687 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700688}
689
690
691void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600692FaceManager::destroyFace(const Interest& request,
693 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700694{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600695 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600696 ndn::nfd::FaceDestroyCommand command;
697
698 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600699 {
700 sendResponse(requestName, 400, "Malformed command");
701 return;
702 }
703
704 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600705 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700706 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700707 target->close();
708 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600709
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600710 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600711
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700712}
713
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600714void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600715FaceManager::onAddFace(shared_ptr<Face> face)
716{
Junxiao Shi6e694322014-04-03 10:27:13 -0700717 ndn::nfd::FaceEventNotification notification;
718 notification.setKind(ndn::nfd::FACE_EVENT_CREATED)
719 .setFaceId(face->getId())
720 .setRemoteUri(face->getRemoteUri().toString())
721 .setLocalUri(face->getLocalUri().toString())
722 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600723
Junxiao Shi6e694322014-04-03 10:27:13 -0700724 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600725}
726
727void
728FaceManager::onRemoveFace(shared_ptr<Face> face)
729{
Junxiao Shi6e694322014-04-03 10:27:13 -0700730 ndn::nfd::FaceEventNotification notification;
731 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
732 .setFaceId(face->getId())
733 .setRemoteUri(face->getRemoteUri().toString())
734 .setLocalUri(face->getLocalUri().toString())
735 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600736
Junxiao Shi6e694322014-04-03 10:27:13 -0700737 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600738}
739
740
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600741bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600742FaceManager::extractLocalControlParameters(const Interest& request,
743 ControlParameters& parameters,
744 ControlCommand& command,
745 shared_ptr<LocalFace>& outFace,
746 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600747{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600748 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600749 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600750 sendResponse(request.getName(), 400, "Malformed command");
751 return false;
752 }
753
754 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
755
756 if (!static_cast<bool>(face))
757 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700758 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600759 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600760 return false;
761 }
762 else if (!face->isLocal())
763 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700764 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
765 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600766 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600767 return false;
768 }
769
770 outFace = dynamic_pointer_cast<LocalFace>(face);
771 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
772
773 return true;
774}
775
776void
777FaceManager::enableLocalControl(const Interest& request,
778 ControlParameters& parameters)
779{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600780 ndn::nfd::FaceEnableLocalControlCommand command;
781
782
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600783 shared_ptr<LocalFace> face;
784 LocalControlFeature feature;
785
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600786 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600787 {
788 face->setLocalControlHeaderFeature(feature, true);
789 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
790 }
791}
792
793void
794FaceManager::disableLocalControl(const Interest& request,
795 ControlParameters& parameters)
796{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600797 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600798 shared_ptr<LocalFace> face;
799 LocalControlFeature feature;
800
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600801 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600802 {
803 face->setLocalControlHeaderFeature(feature, false);
804 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
805 }
806}
807
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600808void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600809FaceManager::listFaces(const Interest& request)
810{
811 const Name& command = request.getName();
812 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700813
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600814 if (commandNComps < LIST_COMMAND_NCOMPS ||
815 !LIST_COMMAND_PREFIX.isPrefixOf(command))
816 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700817 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600818 sendResponse(command, 400, "Malformed command");
819 return;
820 }
821
822 m_statusPublisher.publish();
823}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700824
825} // namespace nfd