blob: 4028ad55ef4eb9d5c217dd1af5cc03a271afef1d [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"
8
9#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060010#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070011#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070012#include "face/tcp-factory.hpp"
13#include "face/udp-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060014
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060015#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
16
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060017#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070018#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060019#endif // HAVE_UNIX_SOCKETS
20
21#ifdef HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070022#include "face/ethernet-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060023#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070024
25namespace nfd {
26
27NFD_LOG_INIT("FaceManager");
28
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060029const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070030
31const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
32 FaceManager::COMMAND_PREFIX.size() +
33 1 + // verb
34 1; // verb options
35
36const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
37 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070038 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070039
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060040const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060042 SignedVerbAndProcessor(
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043 Name::Component("create"),
44 &FaceManager::createFace
45 ),
46
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060047 SignedVerbAndProcessor(
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070048 Name::Component("destroy"),
49 &FaceManager::destroyFace
50 ),
51 };
52
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060053const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
54 {
55 UnsignedVerbAndProcessor(
56 Name::Component("list"),
57 &FaceManager::listFaces
58 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060059
60 UnsignedVerbAndProcessor(
61 Name::Component("events"),
62 &FaceManager::ignoreUnsignedVerb
63 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060064 };
65
66const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
67const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
68
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060069const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070070
71FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070072 shared_ptr<InternalFace> face)
73 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070074 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060075 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060076 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060077 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
78 SIGNED_COMMAND_VERBS +
79 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
80 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
81 UNSIGNED_COMMAND_VERBS +
82 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
83
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070084{
85 face->setInterestFilter("/localhost/nfd/faces",
86 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060087
88 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
89 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070090}
91
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060092FaceManager::~FaceManager()
93{
94
95}
96
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070097void
98FaceManager::setConfigFile(ConfigFile& configFile)
99{
100 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600101 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700102}
103
104
105void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600106FaceManager::onConfig(const ConfigSection& configSection,
107 bool isDryRun,
108 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700109{
110 bool hasSeenUnix = false;
111 bool hasSeenTcp = false;
112 bool hasSeenUdp = false;
113 bool hasSeenEther = false;
114
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600115 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
116
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700117 for (ConfigSection::const_iterator item = configSection.begin();
118 item != configSection.end();
119 ++item)
120 {
121 if (item->first == "unix")
122 {
123 if (hasSeenUnix)
124 throw Error("Duplicate \"unix\" section");
125 hasSeenUnix = true;
126
127 processSectionUnix(item->second, isDryRun);
128 }
129 else if (item->first == "tcp")
130 {
131 if (hasSeenTcp)
132 throw Error("Duplicate \"tcp\" section");
133 hasSeenTcp = true;
134
135 processSectionTcp(item->second, isDryRun);
136 }
137 else if (item->first == "udp")
138 {
139 if (hasSeenUdp)
140 throw Error("Duplicate \"udp\" section");
141 hasSeenUdp = true;
142
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600143 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700144 }
145 else if (item->first == "ether")
146 {
147 if (hasSeenEther)
148 throw Error("Duplicate \"ether\" section");
149 hasSeenEther = true;
150
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600151 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700152 }
153 else
154 {
155 throw Error("Unrecognized option \"" + item->first + "\"");
156 }
157 }
158}
159
160void
161FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
162{
163 // ; the unix section contains settings of UNIX stream faces and channels
164 // unix
165 // {
166 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
167 // path /var/run/nfd.sock ; UNIX stream listener path
168 // }
169
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600170#if defined(HAVE_UNIX_SOCKETS)
171
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700172 bool needToListen = true;
173 std::string path = "/var/run/nfd.sock";
174
175 for (ConfigSection::const_iterator i = configSection.begin();
176 i != configSection.end();
177 ++i)
178 {
179 if (i->first == "path")
180 {
181 path = i->second.get_value<std::string>();
182 }
183 else if (i->first == "listen")
184 {
185 needToListen = parseYesNo(i, i->first, "unix");
186 }
187 else
188 {
189 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
190 }
191 }
192
193 if (!isDryRun)
194 {
195 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
196 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
197
198 if (needToListen)
199 {
200 // Should acceptFailed callback be used somehow?
201 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
202 UnixStreamChannel::ConnectFailedCallback());
203 }
204
205 m_factories.insert(std::make_pair("unix", factory));
206 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600207#else
208 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
209#endif // HAVE_UNIX_SOCKETS
210
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700211}
212
213void
214FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
215{
216 // ; the tcp section contains settings of TCP faces and channels
217 // tcp
218 // {
219 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
220 // port 6363 ; TCP listener port number
221 // }
222
223 std::string port = "6363";
224 bool needToListen = true;
225
226 for (ConfigSection::const_iterator i = configSection.begin();
227 i != configSection.end();
228 ++i)
229 {
230 if (i->first == "port")
231 {
232 port = i->second.get_value<std::string>();
233 }
234 else if (i->first == "listen")
235 {
236 needToListen = parseYesNo(i, i->first, "tcp");
237 }
238 else
239 {
240 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
241 }
242 }
243
244 if (!isDryRun)
245 {
246 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
247
248 using namespace boost::asio::ip;
249
250 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
251 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
252
253 if (needToListen)
254 {
255 // Should acceptFailed callback be used somehow?
256
257 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
258 TcpChannel::ConnectFailedCallback());
259 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
260 TcpChannel::ConnectFailedCallback());
261 }
262
263 m_factories.insert(std::make_pair("tcp", factory));
264 m_factories.insert(std::make_pair("tcp4", factory));
265 m_factories.insert(std::make_pair("tcp6", factory));
266 }
267}
268
269void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600270FaceManager::processSectionUdp(const ConfigSection& configSection,
271 bool isDryRun,
272 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700273{
274 // ; the udp section contains settings of UDP faces and channels
275 // udp
276 // {
277 // port 6363 ; UDP unicast port number
278 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
279 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
280
281 // ; NFD creates one UDP multicast face per NIC
282 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
283 // mcast_port 56363 ; UDP multicast port number
284 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
285 // }
286
287 std::string port = "6363";
288 size_t timeout = 30;
289 size_t keepAliveInterval = 25;
290 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600291 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700292 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600293
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700294
295 for (ConfigSection::const_iterator i = configSection.begin();
296 i != configSection.end();
297 ++i)
298 {
299 if (i->first == "port")
300 {
301 port = i->second.get_value<std::string>();
302 }
303 else if (i->first == "idle_timeout")
304 {
305 try
306 {
307 timeout = i->second.get_value<size_t>();
308 }
309 catch (const std::exception& e)
310 {
311 throw ConfigFile::Error("Invalid value for option \"" +
312 i->first + "\" in \"udp\" section");
313 }
314 }
315 else if (i->first == "keep_alive_interval")
316 {
317 try
318 {
319 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700320
321 /// \todo Make use of keepAliveInterval
322 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700323 }
324 catch (const std::exception& e)
325 {
326 throw ConfigFile::Error("Invalid value for option \"" +
327 i->first + "\" in \"udp\" section");
328 }
329 }
330 else if (i->first == "mcast")
331 {
332 useMcast = parseYesNo(i, i->first, "udp");
333 }
334 else if (i->first == "mcast_port")
335 {
336 mcastPort = i->second.get_value<std::string>();
337 }
338 else if (i->first == "mcast_group")
339 {
340 using namespace boost::asio::ip;
341 mcastGroup = i->second.get_value<std::string>();
342 try
343 {
344 address mcastGroupTest = address::from_string(mcastGroup);
345 if (!mcastGroupTest.is_v4())
346 {
347 throw ConfigFile::Error("Invalid value for option \"" +
348 i->first + "\" in \"udp\" section");
349 }
350 }
351 catch(const std::runtime_error& e)
352 {
353 throw ConfigFile::Error("Invalid value for option \"" +
354 i->first + "\" in \"udp\" section");
355 }
356 }
357 else
358 {
359 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
360 }
361 }
362
363 /// \todo what is keep alive interval used for?
364
365 if (!isDryRun)
366 {
367 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
368
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600369 factory->createChannel("::", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700370
371 m_factories.insert(std::make_pair("udp", factory));
372 m_factories.insert(std::make_pair("udp4", factory));
373 m_factories.insert(std::make_pair("udp6", factory));
374
375 if (useMcast)
376 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600377 bool useEndpoint = false;
378 udp::Endpoint localEndpoint;
379
380 try
381 {
382 localEndpoint.port(boost::lexical_cast<uint16_t>(port));
383 useEndpoint = true;
384 }
385 catch (const boost::bad_lexical_cast& error)
386 {
387 NFD_LOG_DEBUG("Treating UDP port \"" << port << "\" as a service name");
388 }
389
390 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
391 i != nicList.end();
392 ++i)
393 {
394 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
395 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
396 {
397 shared_ptr<MulticastUdpFace> newFace =
398 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
399 mcastGroup, mcastPort);
400
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700401 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600402
403 if (useEndpoint)
404 {
405 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
406 nic->ipv4Addresses.begin();
407 j != nic->ipv4Addresses.end();
408 ++j)
409 {
410 localEndpoint.address(*j);
411 factory->createChannel(localEndpoint, time::seconds(timeout));
412 }
413 }
414 else
415 {
416 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
417 nic->ipv4Addresses.begin();
418 j != nic->ipv4Addresses.end();
419 ++j)
420 {
421 factory->createChannel(j->to_string(), port, time::seconds(timeout));
422 }
423 }
424 }
425 }
426 }
427 else
428 {
429 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700430 }
431 }
432}
433
434void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600435FaceManager::processSectionEther(const ConfigSection& configSection,
436 bool isDryRun,
437 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700438{
439 // ; the ether section contains settings of Ethernet faces and channels
440 // ether
441 // {
442 // ; NFD creates one Ethernet multicast face per NIC
443 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
444 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
445 // }
446
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600447#if defined(HAVE_PCAP)
448
449 using ethernet::Address;
450
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700451 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600452 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700453
454 for (ConfigSection::const_iterator i = configSection.begin();
455 i != configSection.end();
456 ++i)
457 {
458 if (i->first == "mcast")
459 {
460 useMcast = parseYesNo(i, i->first, "ether");
461 }
462
463 else if (i->first == "mcast_group")
464 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600465 mcastGroup = Address::fromString(i->second.get_value<std::string>());
466 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700467 {
468 throw ConfigFile::Error("Invalid value for option \"" +
469 i->first + "\" in \"ether\" section");
470 }
471 }
472 else
473 {
474 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
475 }
476 }
477
478 if (!isDryRun)
479 {
480 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
481 m_factories.insert(std::make_pair("ether", factory));
482
483 if (useMcast)
484 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600485 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
486 i != nicList.end();
487 ++i)
488 {
489 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
490 if (nic->isUp() && nic->isMulticastCapable())
491 {
492 try
493 {
494 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100495 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700496
497 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600498 }
499 catch (const EthernetFactory::Error& factoryError)
500 {
501 NFD_LOG_ERROR(factoryError.what() << ", continuing");
502 }
503 catch (const EthernetFace::Error& faceError)
504 {
505 NFD_LOG_ERROR(faceError.what() << ", continuing");
506 }
507 }
508 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700509 }
510 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600511#else
512 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
513#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700514}
515
516
517void
518FaceManager::onFaceRequest(const Interest& request)
519{
520 const Name& command = request.getName();
521 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600522 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700523
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600524 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
525 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
526 {
527 NFD_LOG_INFO("command result: processing verb: " << verb);
528 (unsignedVerbProcessor->second)(this, boost::cref(request));
529 }
530 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700531 commandNComps < COMMAND_SIGNED_NCOMPS)
532 {
533 NFD_LOG_INFO("command result: unsigned verb: " << command);
534 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700535 }
536 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
537 !COMMAND_PREFIX.isPrefixOf(command))
538 {
539 NFD_LOG_INFO("command result: malformed");
540 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700541 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600542 else
543 {
544 validate(request,
545 bind(&FaceManager::onValidatedFaceRequest, this, _1),
546 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
547 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700548}
549
550void
551FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
552{
553 const Name& command = request->getName();
554 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
555
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600556 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
557 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700558 {
559 ndn::nfd::FaceManagementOptions options;
560 if (!extractOptions(*request, options))
561 {
562 sendResponse(command, 400, "Malformed command");
563 return;
564 }
565
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700566 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600567 (signedVerbProcessor->second)(this, command, options);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700568 }
569 else
570 {
571 NFD_LOG_INFO("command result: unsupported verb: " << verb);
572 sendResponse(command, 501, "Unsupported command");
573 }
574
575}
576
577bool
578FaceManager::extractOptions(const Interest& request,
579 ndn::nfd::FaceManagementOptions& extractedOptions)
580{
581 const Name& command = request.getName();
582 const size_t optionCompIndex =
583 COMMAND_PREFIX.size() + 1;
584
585 try
586 {
587 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
588 extractedOptions.wireDecode(rawOptions);
589 }
590 catch (const ndn::Tlv::Error& e)
591 {
592 NFD_LOG_INFO("Bad command option parse: " << command);
593 return false;
594 }
595 NFD_LOG_DEBUG("Options parsed OK");
596 return true;
597}
598
599void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700600FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
601{
602 m_faceTable.add(newFace);
603
604 NFD_LOG_INFO("Created face " << newFace->getUri() << " ID " << newFace->getId());
605}
606
607void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700608FaceManager::onCreated(const Name& requestName,
609 ndn::nfd::FaceManagementOptions& options,
610 const shared_ptr<Face>& newFace)
611{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700612 addCreatedFaceToForwarder(newFace);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700613
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700614 options.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700615
616 ndn::nfd::ControlResponse response;
617 setResponse(response, 200, "Success", options.wireEncode());
618 sendResponse(requestName, response);
619}
620
621void
622FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
623{
624 NFD_LOG_INFO("Failed to create face: " << reason);
625 sendResponse(requestName, 400, "Failed to create face");
626}
627
628void
629FaceManager::createFace(const Name& requestName,
630 ndn::nfd::FaceManagementOptions& options)
631{
632 FaceUri uri;
633 if (!uri.parse(options.getUri()))
634 {
635 sendResponse(requestName, 400, "Malformed command");
636 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
646 factory->second->createFace(uri,
647 bind(&FaceManager::onCreated, this, requestName, options, _1),
648 bind(&FaceManager::onConnectFailed, this, requestName, _1));
649}
650
651
652void
653FaceManager::destroyFace(const Name& requestName,
654 ndn::nfd::FaceManagementOptions& options)
655{
656 shared_ptr<Face> target = m_faceTable.get(options.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600657 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700658 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700659 target->close();
660 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600661
662 ndn::nfd::ControlResponse response;
663 setResponse(response, 200, "Success", options.wireEncode());
664 sendResponse(requestName, response);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700665}
666
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600667void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600668FaceManager::onAddFace(shared_ptr<Face> face)
669{
670 ndn::nfd::FaceEventNotification faceCreated(ndn::nfd::FACE_EVENT_CREATED,
671 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700672 face->getUri().toString(),
673 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
674 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600675
676 m_notificationStream.postNotification(faceCreated);
677}
678
679void
680FaceManager::onRemoveFace(shared_ptr<Face> face)
681{
682 ndn::nfd::FaceEventNotification faceDestroyed(ndn::nfd::FACE_EVENT_DESTROYED,
683 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700684 face->getUri().toString(),
685 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
686 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600687
688 m_notificationStream.postNotification(faceDestroyed);
689}
690
691
692void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600693FaceManager::listFaces(const Interest& request)
694{
695 const Name& command = request.getName();
696 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700697
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600698 if (commandNComps < LIST_COMMAND_NCOMPS ||
699 !LIST_COMMAND_PREFIX.isPrefixOf(command))
700 {
701 NFD_LOG_INFO("command result: malformed");
702 sendResponse(command, 400, "Malformed command");
703 return;
704 }
705
706 m_statusPublisher.publish();
707}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700708
709} // namespace nfd