blob: 406d524e2a4ffc928fe8ad206c0e0390e4e67bb0 [file] [log] [blame]
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "face-manager.hpp"
Junxiao Shi6e694322014-04-03 10:27:13 -07008#include "face-flags.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07009
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060010#include "core/logger.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070011#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060012#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070013#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070014#include "face/tcp-factory.hpp"
15#include "face/udp-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060016
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060017#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
18
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060019#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070020#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060021#endif // HAVE_UNIX_SOCKETS
22
23#ifdef HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070024#include "face/ethernet-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060025#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070026
27namespace nfd {
28
29NFD_LOG_INIT("FaceManager");
30
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060031const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070032
33const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
34 FaceManager::COMMAND_PREFIX.size() +
35 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060036 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037
38const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
39 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070040 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060042const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060044 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060045 Name::Component("create"),
46 &FaceManager::createFace
47 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070048
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060049 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060050 Name::Component("destroy"),
51 &FaceManager::destroyFace
52 ),
53
54 SignedVerbAndProcessor(
55 Name::Component("enable-local-control"),
56 &FaceManager::enableLocalControl
57 ),
58
59 SignedVerbAndProcessor(
60 Name::Component("disable-local-control"),
61 &FaceManager::disableLocalControl
62 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070063 };
64
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060065const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
66 {
67 UnsignedVerbAndProcessor(
68 Name::Component("list"),
69 &FaceManager::listFaces
70 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060071
72 UnsignedVerbAndProcessor(
73 Name::Component("events"),
74 &FaceManager::ignoreUnsignedVerb
75 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060076 };
77
78const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
79const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
80
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060081const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070082
83FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070084 shared_ptr<InternalFace> face)
85 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070086 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060087 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060088 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060089 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060090 SIGNED_COMMAND_VERBS +
91 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060092 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060093 UNSIGNED_COMMAND_VERBS +
94 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060095
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070096{
97 face->setInterestFilter("/localhost/nfd/faces",
98 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060099
100 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
101 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700102}
103
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600104FaceManager::~FaceManager()
105{
106
107}
108
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700109void
110FaceManager::setConfigFile(ConfigFile& configFile)
111{
112 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600113 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700114}
115
116
117void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600118FaceManager::onConfig(const ConfigSection& configSection,
119 bool isDryRun,
120 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700121{
122 bool hasSeenUnix = false;
123 bool hasSeenTcp = false;
124 bool hasSeenUdp = false;
125 bool hasSeenEther = false;
126
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600127 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
128
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700129 for (ConfigSection::const_iterator item = configSection.begin();
130 item != configSection.end();
131 ++item)
132 {
133 if (item->first == "unix")
134 {
135 if (hasSeenUnix)
136 throw Error("Duplicate \"unix\" section");
137 hasSeenUnix = true;
138
139 processSectionUnix(item->second, isDryRun);
140 }
141 else if (item->first == "tcp")
142 {
143 if (hasSeenTcp)
144 throw Error("Duplicate \"tcp\" section");
145 hasSeenTcp = true;
146
147 processSectionTcp(item->second, isDryRun);
148 }
149 else if (item->first == "udp")
150 {
151 if (hasSeenUdp)
152 throw Error("Duplicate \"udp\" section");
153 hasSeenUdp = true;
154
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600155 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700156 }
157 else if (item->first == "ether")
158 {
159 if (hasSeenEther)
160 throw Error("Duplicate \"ether\" section");
161 hasSeenEther = true;
162
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600163 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700164 }
165 else
166 {
167 throw Error("Unrecognized option \"" + item->first + "\"");
168 }
169 }
170}
171
172void
173FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
174{
175 // ; the unix section contains settings of UNIX stream faces and channels
176 // unix
177 // {
178 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
179 // path /var/run/nfd.sock ; UNIX stream listener path
180 // }
181
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600182#if defined(HAVE_UNIX_SOCKETS)
183
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700184 bool needToListen = true;
185 std::string path = "/var/run/nfd.sock";
186
187 for (ConfigSection::const_iterator i = configSection.begin();
188 i != configSection.end();
189 ++i)
190 {
191 if (i->first == "path")
192 {
193 path = i->second.get_value<std::string>();
194 }
195 else if (i->first == "listen")
196 {
197 needToListen = parseYesNo(i, i->first, "unix");
198 }
199 else
200 {
201 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
202 }
203 }
204
205 if (!isDryRun)
206 {
207 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
208 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
209
210 if (needToListen)
211 {
212 // Should acceptFailed callback be used somehow?
213 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
214 UnixStreamChannel::ConnectFailedCallback());
215 }
216
217 m_factories.insert(std::make_pair("unix", factory));
218 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600219#else
220 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
221#endif // HAVE_UNIX_SOCKETS
222
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700223}
224
225void
226FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
227{
228 // ; the tcp section contains settings of TCP faces and channels
229 // tcp
230 // {
231 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
232 // port 6363 ; TCP listener port number
233 // }
234
235 std::string port = "6363";
236 bool needToListen = true;
237
238 for (ConfigSection::const_iterator i = configSection.begin();
239 i != configSection.end();
240 ++i)
241 {
242 if (i->first == "port")
243 {
244 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600245 try
246 {
247 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
248 NFD_LOG_TRACE("TCP port set to " << portNo);
249 }
250 catch (const std::bad_cast& error)
251 {
252 throw ConfigFile::Error("Invalid value for option " +
253 i->first + "\" in \"udp\" section");
254 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700255 }
256 else if (i->first == "listen")
257 {
258 needToListen = parseYesNo(i, i->first, "tcp");
259 }
260 else
261 {
262 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
263 }
264 }
265
266 if (!isDryRun)
267 {
268 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
269
270 using namespace boost::asio::ip;
271
272 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
273 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
274
275 if (needToListen)
276 {
277 // Should acceptFailed callback be used somehow?
278
279 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
280 TcpChannel::ConnectFailedCallback());
281 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
282 TcpChannel::ConnectFailedCallback());
283 }
284
285 m_factories.insert(std::make_pair("tcp", factory));
286 m_factories.insert(std::make_pair("tcp4", factory));
287 m_factories.insert(std::make_pair("tcp6", factory));
288 }
289}
290
291void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600292FaceManager::processSectionUdp(const ConfigSection& configSection,
293 bool isDryRun,
294 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700295{
296 // ; the udp section contains settings of UDP faces and channels
297 // udp
298 // {
299 // port 6363 ; UDP unicast port number
300 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
301 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
302
303 // ; NFD creates one UDP multicast face per NIC
304 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
305 // mcast_port 56363 ; UDP multicast port number
306 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
307 // }
308
309 std::string port = "6363";
310 size_t timeout = 30;
311 size_t keepAliveInterval = 25;
312 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600313 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700314 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600315
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700316
317 for (ConfigSection::const_iterator i = configSection.begin();
318 i != configSection.end();
319 ++i)
320 {
321 if (i->first == "port")
322 {
323 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600324 try
325 {
326 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
327 NFD_LOG_TRACE("UDP port set to " << portNo);
328 }
329 catch (const std::bad_cast& error)
330 {
331 throw ConfigFile::Error("Invalid value for option " +
332 i->first + "\" in \"udp\" section");
333 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700334 }
335 else if (i->first == "idle_timeout")
336 {
337 try
338 {
339 timeout = i->second.get_value<size_t>();
340 }
341 catch (const std::exception& e)
342 {
343 throw ConfigFile::Error("Invalid value for option \"" +
344 i->first + "\" in \"udp\" section");
345 }
346 }
347 else if (i->first == "keep_alive_interval")
348 {
349 try
350 {
351 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700352
353 /// \todo Make use of keepAliveInterval
354 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700355 }
356 catch (const std::exception& e)
357 {
358 throw ConfigFile::Error("Invalid value for option \"" +
359 i->first + "\" in \"udp\" section");
360 }
361 }
362 else if (i->first == "mcast")
363 {
364 useMcast = parseYesNo(i, i->first, "udp");
365 }
366 else if (i->first == "mcast_port")
367 {
368 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600369 try
370 {
371 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
372 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
373 }
374 catch (const std::bad_cast& error)
375 {
376 throw ConfigFile::Error("Invalid value for option " +
377 i->first + "\" in \"udp\" section");
378 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700379 }
380 else if (i->first == "mcast_group")
381 {
382 using namespace boost::asio::ip;
383 mcastGroup = i->second.get_value<std::string>();
384 try
385 {
386 address mcastGroupTest = address::from_string(mcastGroup);
387 if (!mcastGroupTest.is_v4())
388 {
389 throw ConfigFile::Error("Invalid value for option \"" +
390 i->first + "\" in \"udp\" section");
391 }
392 }
393 catch(const std::runtime_error& e)
394 {
395 throw ConfigFile::Error("Invalid value for option \"" +
396 i->first + "\" in \"udp\" section");
397 }
398 }
399 else
400 {
401 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
402 }
403 }
404
405 /// \todo what is keep alive interval used for?
406
407 if (!isDryRun)
408 {
409 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
410
Steve DiBenedettob9906cf2014-03-27 09:18:28 -0600411 shared_ptr<UdpChannel> v4Channel =
412 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
413
414 shared_ptr<UdpChannel> v6Channel =
415 factory->createChannel("::", port, time::seconds(timeout));
416
417 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
418 UdpChannel::ConnectFailedCallback());
419
420 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
421 UdpChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700422
423 m_factories.insert(std::make_pair("udp", factory));
424 m_factories.insert(std::make_pair("udp4", factory));
425 m_factories.insert(std::make_pair("udp6", factory));
426
427 if (useMcast)
428 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600429 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
430 i != nicList.end();
431 ++i)
432 {
433 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
434 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
435 {
436 shared_ptr<MulticastUdpFace> newFace =
437 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
438 mcastGroup, mcastPort);
439
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700440 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600441 }
442 }
443 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700444 }
445}
446
447void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600448FaceManager::processSectionEther(const ConfigSection& configSection,
449 bool isDryRun,
450 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700451{
452 // ; the ether section contains settings of Ethernet faces and channels
453 // ether
454 // {
455 // ; NFD creates one Ethernet multicast face per NIC
456 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
457 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
458 // }
459
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600460#if defined(HAVE_PCAP)
461
462 using ethernet::Address;
463
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700464 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600465 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700466
467 for (ConfigSection::const_iterator i = configSection.begin();
468 i != configSection.end();
469 ++i)
470 {
471 if (i->first == "mcast")
472 {
473 useMcast = parseYesNo(i, i->first, "ether");
474 }
475
476 else if (i->first == "mcast_group")
477 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600478 mcastGroup = Address::fromString(i->second.get_value<std::string>());
479 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700480 {
481 throw ConfigFile::Error("Invalid value for option \"" +
482 i->first + "\" in \"ether\" section");
483 }
484 }
485 else
486 {
487 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
488 }
489 }
490
491 if (!isDryRun)
492 {
493 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
494 m_factories.insert(std::make_pair("ether", factory));
495
496 if (useMcast)
497 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600498 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
499 i != nicList.end();
500 ++i)
501 {
502 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
503 if (nic->isUp() && nic->isMulticastCapable())
504 {
505 try
506 {
507 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100508 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700509
510 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600511 }
512 catch (const EthernetFactory::Error& factoryError)
513 {
514 NFD_LOG_ERROR(factoryError.what() << ", continuing");
515 }
516 catch (const EthernetFace::Error& faceError)
517 {
518 NFD_LOG_ERROR(faceError.what() << ", continuing");
519 }
520 }
521 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700522 }
523 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600524#else
525 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
526#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700527}
528
529
530void
531FaceManager::onFaceRequest(const Interest& request)
532{
533 const Name& command = request.getName();
534 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600535 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700536
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600537 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
538 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
539 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700540 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600541 (unsignedVerbProcessor->second)(this, boost::cref(request));
542 }
543 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600544 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700545 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700546 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700547 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700548 }
549 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
550 !COMMAND_PREFIX.isPrefixOf(command))
551 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700552 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700553 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700554 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600555 else
556 {
557 validate(request,
558 bind(&FaceManager::onValidatedFaceRequest, this, _1),
559 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
560 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700561}
562
563void
564FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
565{
566 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600567 const Name::Component& verb = command[COMMAND_PREFIX.size()];
568 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700569
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600570 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
571 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700572 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600573 ControlParameters parameters;
574 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700575 {
576 sendResponse(command, 400, "Malformed command");
577 return;
578 }
579
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700580 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600581 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700582 }
583 else
584 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700585 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700586 sendResponse(command, 501, "Unsupported command");
587 }
588
589}
590
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700591void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700592FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
593{
594 m_faceTable.add(newFace);
595
Junxiao Shi6e694322014-04-03 10:27:13 -0700596 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700597}
598
599void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700600FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600601 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700602 const shared_ptr<Face>& newFace)
603{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700604 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600605 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700606
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600607 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700608}
609
610void
611FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
612{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700613 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600614 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700615}
616
617void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600618FaceManager::createFace(const Interest& request,
619 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700620{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600621 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600622 ndn::nfd::FaceCreateCommand command;
623
624 if (!validateParameters(command, parameters))
625 {
626 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600627 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600628 return;
629 }
630
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700631 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600632 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700633 {
634 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600635 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700636 return;
637 }
638
639 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
640 if (factory == m_factories.end())
641 {
642 sendResponse(requestName, 501, "Unsupported protocol");
643 return;
644 }
645
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600646 try
647 {
648 factory->second->createFace(uri,
649 bind(&FaceManager::onCreated,
650 this, requestName, parameters, _1),
651 bind(&FaceManager::onConnectFailed,
652 this, requestName, _1));
653 }
654 catch (const std::runtime_error& error)
655 {
656 std::string errorMessage = "NFD error: ";
657 errorMessage += error.what();
658
659 NFD_LOG_ERROR(errorMessage);
660 sendResponse(requestName, 500, errorMessage);
661 }
662 catch (const std::logic_error& error)
663 {
664 std::string errorMessage = "NFD error: ";
665 errorMessage += error.what();
666
667 NFD_LOG_ERROR(errorMessage);
668 sendResponse(requestName, 500, errorMessage);
669 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700670}
671
672
673void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600674FaceManager::destroyFace(const Interest& request,
675 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700676{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600677 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600678 ndn::nfd::FaceDestroyCommand command;
679
680 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600681 {
682 sendResponse(requestName, 400, "Malformed command");
683 return;
684 }
685
686 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600687 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700688 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700689 target->close();
690 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600691
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600692 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600693
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700694}
695
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600696void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600697FaceManager::onAddFace(shared_ptr<Face> face)
698{
Junxiao Shi6e694322014-04-03 10:27:13 -0700699 ndn::nfd::FaceEventNotification notification;
700 notification.setKind(ndn::nfd::FACE_EVENT_CREATED)
701 .setFaceId(face->getId())
702 .setRemoteUri(face->getRemoteUri().toString())
703 .setLocalUri(face->getLocalUri().toString())
704 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600705
Junxiao Shi6e694322014-04-03 10:27:13 -0700706 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600707}
708
709void
710FaceManager::onRemoveFace(shared_ptr<Face> face)
711{
Junxiao Shi6e694322014-04-03 10:27:13 -0700712 ndn::nfd::FaceEventNotification notification;
713 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
714 .setFaceId(face->getId())
715 .setRemoteUri(face->getRemoteUri().toString())
716 .setLocalUri(face->getLocalUri().toString())
717 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600718
Junxiao Shi6e694322014-04-03 10:27:13 -0700719 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600720}
721
722
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600723bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600724FaceManager::extractLocalControlParameters(const Interest& request,
725 ControlParameters& parameters,
726 ControlCommand& command,
727 shared_ptr<LocalFace>& outFace,
728 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600729{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600730 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600731 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600732 sendResponse(request.getName(), 400, "Malformed command");
733 return false;
734 }
735
736 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
737
738 if (!static_cast<bool>(face))
739 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700740 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600741 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600742 return false;
743 }
744 else if (!face->isLocal())
745 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700746 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
747 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600748 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600749 return false;
750 }
751
752 outFace = dynamic_pointer_cast<LocalFace>(face);
753 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
754
755 return true;
756}
757
758void
759FaceManager::enableLocalControl(const Interest& request,
760 ControlParameters& parameters)
761{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600762 ndn::nfd::FaceEnableLocalControlCommand command;
763
764
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600765 shared_ptr<LocalFace> face;
766 LocalControlFeature feature;
767
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600768 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600769 {
770 face->setLocalControlHeaderFeature(feature, true);
771 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
772 }
773}
774
775void
776FaceManager::disableLocalControl(const Interest& request,
777 ControlParameters& parameters)
778{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600779 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600780 shared_ptr<LocalFace> face;
781 LocalControlFeature feature;
782
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600783 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600784 {
785 face->setLocalControlHeaderFeature(feature, false);
786 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
787 }
788}
789
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600790void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600791FaceManager::listFaces(const Interest& request)
792{
793 const Name& command = request.getName();
794 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700795
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600796 if (commandNComps < LIST_COMMAND_NCOMPS ||
797 !LIST_COMMAND_PREFIX.isPrefixOf(command))
798 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700799 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600800 sendResponse(command, 400, "Malformed command");
801 return;
802 }
803
804 m_statusPublisher.publish();
805}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700806
807} // namespace nfd