blob: bbd495e37feab6642549d0b90f8e326f99a67bcc [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>();
320 }
321 catch (const std::exception& e)
322 {
323 throw ConfigFile::Error("Invalid value for option \"" +
324 i->first + "\" in \"udp\" section");
325 }
326 }
327 else if (i->first == "mcast")
328 {
329 useMcast = parseYesNo(i, i->first, "udp");
330 }
331 else if (i->first == "mcast_port")
332 {
333 mcastPort = i->second.get_value<std::string>();
334 }
335 else if (i->first == "mcast_group")
336 {
337 using namespace boost::asio::ip;
338 mcastGroup = i->second.get_value<std::string>();
339 try
340 {
341 address mcastGroupTest = address::from_string(mcastGroup);
342 if (!mcastGroupTest.is_v4())
343 {
344 throw ConfigFile::Error("Invalid value for option \"" +
345 i->first + "\" in \"udp\" section");
346 }
347 }
348 catch(const std::runtime_error& e)
349 {
350 throw ConfigFile::Error("Invalid value for option \"" +
351 i->first + "\" in \"udp\" section");
352 }
353 }
354 else
355 {
356 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
357 }
358 }
359
360 /// \todo what is keep alive interval used for?
361
362 if (!isDryRun)
363 {
364 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
365
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600366 factory->createChannel("::", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700367
368 m_factories.insert(std::make_pair("udp", factory));
369 m_factories.insert(std::make_pair("udp4", factory));
370 m_factories.insert(std::make_pair("udp6", factory));
371
372 if (useMcast)
373 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600374 bool useEndpoint = false;
375 udp::Endpoint localEndpoint;
376
377 try
378 {
379 localEndpoint.port(boost::lexical_cast<uint16_t>(port));
380 useEndpoint = true;
381 }
382 catch (const boost::bad_lexical_cast& error)
383 {
384 NFD_LOG_DEBUG("Treating UDP port \"" << port << "\" as a service name");
385 }
386
387 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
388 i != nicList.end();
389 ++i)
390 {
391 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
392 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
393 {
394 shared_ptr<MulticastUdpFace> newFace =
395 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
396 mcastGroup, mcastPort);
397
398 NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
399
400 if (useEndpoint)
401 {
402 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
403 nic->ipv4Addresses.begin();
404 j != nic->ipv4Addresses.end();
405 ++j)
406 {
407 localEndpoint.address(*j);
408 factory->createChannel(localEndpoint, time::seconds(timeout));
409 }
410 }
411 else
412 {
413 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
414 nic->ipv4Addresses.begin();
415 j != nic->ipv4Addresses.end();
416 ++j)
417 {
418 factory->createChannel(j->to_string(), port, time::seconds(timeout));
419 }
420 }
421 }
422 }
423 }
424 else
425 {
426 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700427 }
428 }
429}
430
431void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600432FaceManager::processSectionEther(const ConfigSection& configSection,
433 bool isDryRun,
434 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700435{
436 // ; the ether section contains settings of Ethernet faces and channels
437 // ether
438 // {
439 // ; NFD creates one Ethernet multicast face per NIC
440 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
441 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
442 // }
443
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600444#if defined(HAVE_PCAP)
445
446 using ethernet::Address;
447
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700448 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600449 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700450
451 for (ConfigSection::const_iterator i = configSection.begin();
452 i != configSection.end();
453 ++i)
454 {
455 if (i->first == "mcast")
456 {
457 useMcast = parseYesNo(i, i->first, "ether");
458 }
459
460 else if (i->first == "mcast_group")
461 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600462 mcastGroup = Address::fromString(i->second.get_value<std::string>());
463 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700464 {
465 throw ConfigFile::Error("Invalid value for option \"" +
466 i->first + "\" in \"ether\" section");
467 }
468 }
469 else
470 {
471 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
472 }
473 }
474
475 if (!isDryRun)
476 {
477 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
478 m_factories.insert(std::make_pair("ether", factory));
479
480 if (useMcast)
481 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600482 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
483 i != nicList.end();
484 ++i)
485 {
486 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
487 if (nic->isUp() && nic->isMulticastCapable())
488 {
489 try
490 {
491 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100492 factory->createMulticastFace(nic, mcastGroup);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600493 NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
494 }
495 catch (const EthernetFactory::Error& factoryError)
496 {
497 NFD_LOG_ERROR(factoryError.what() << ", continuing");
498 }
499 catch (const EthernetFace::Error& faceError)
500 {
501 NFD_LOG_ERROR(faceError.what() << ", continuing");
502 }
503 }
504 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700505 }
506 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600507#else
508 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
509#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700510}
511
512
513void
514FaceManager::onFaceRequest(const Interest& request)
515{
516 const Name& command = request.getName();
517 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600518 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700519
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600520 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
521 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
522 {
523 NFD_LOG_INFO("command result: processing verb: " << verb);
524 (unsignedVerbProcessor->second)(this, boost::cref(request));
525 }
526 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700527 commandNComps < COMMAND_SIGNED_NCOMPS)
528 {
529 NFD_LOG_INFO("command result: unsigned verb: " << command);
530 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700531 }
532 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
533 !COMMAND_PREFIX.isPrefixOf(command))
534 {
535 NFD_LOG_INFO("command result: malformed");
536 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700537 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600538 else
539 {
540 validate(request,
541 bind(&FaceManager::onValidatedFaceRequest, this, _1),
542 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
543 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700544}
545
546void
547FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
548{
549 const Name& command = request->getName();
550 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
551
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600552 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
553 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700554 {
555 ndn::nfd::FaceManagementOptions options;
556 if (!extractOptions(*request, options))
557 {
558 sendResponse(command, 400, "Malformed command");
559 return;
560 }
561
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700562 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600563 (signedVerbProcessor->second)(this, command, options);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700564 }
565 else
566 {
567 NFD_LOG_INFO("command result: unsupported verb: " << verb);
568 sendResponse(command, 501, "Unsupported command");
569 }
570
571}
572
573bool
574FaceManager::extractOptions(const Interest& request,
575 ndn::nfd::FaceManagementOptions& extractedOptions)
576{
577 const Name& command = request.getName();
578 const size_t optionCompIndex =
579 COMMAND_PREFIX.size() + 1;
580
581 try
582 {
583 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
584 extractedOptions.wireDecode(rawOptions);
585 }
586 catch (const ndn::Tlv::Error& e)
587 {
588 NFD_LOG_INFO("Bad command option parse: " << command);
589 return false;
590 }
591 NFD_LOG_DEBUG("Options parsed OK");
592 return true;
593}
594
595void
596FaceManager::onCreated(const Name& requestName,
597 ndn::nfd::FaceManagementOptions& options,
598 const shared_ptr<Face>& newFace)
599{
600 m_faceTable.add(newFace);
601 options.setFaceId(newFace->getId());
602
603 NFD_LOG_INFO("Created Face ID " << newFace->getId());
604
605 ndn::nfd::ControlResponse response;
606 setResponse(response, 200, "Success", options.wireEncode());
607 sendResponse(requestName, response);
608}
609
610void
611FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
612{
613 NFD_LOG_INFO("Failed to create face: " << reason);
614 sendResponse(requestName, 400, "Failed to create face");
615}
616
617void
618FaceManager::createFace(const Name& requestName,
619 ndn::nfd::FaceManagementOptions& options)
620{
621 FaceUri uri;
622 if (!uri.parse(options.getUri()))
623 {
624 sendResponse(requestName, 400, "Malformed command");
625 return;
626 }
627
628 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
629 if (factory == m_factories.end())
630 {
631 sendResponse(requestName, 501, "Unsupported protocol");
632 return;
633 }
634
635 factory->second->createFace(uri,
636 bind(&FaceManager::onCreated, this, requestName, options, _1),
637 bind(&FaceManager::onConnectFailed, this, requestName, _1));
638}
639
640
641void
642FaceManager::destroyFace(const Name& requestName,
643 ndn::nfd::FaceManagementOptions& options)
644{
645 shared_ptr<Face> target = m_faceTable.get(options.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600646 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700647 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700648 target->close();
649 }
650 sendResponse(requestName, 200, "Success");
651}
652
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600653void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600654FaceManager::onAddFace(shared_ptr<Face> face)
655{
656 ndn::nfd::FaceEventNotification faceCreated(ndn::nfd::FACE_EVENT_CREATED,
657 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700658 face->getUri().toString(),
659 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
660 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600661
662 m_notificationStream.postNotification(faceCreated);
663}
664
665void
666FaceManager::onRemoveFace(shared_ptr<Face> face)
667{
668 ndn::nfd::FaceEventNotification faceDestroyed(ndn::nfd::FACE_EVENT_DESTROYED,
669 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700670 face->getUri().toString(),
671 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
672 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600673
674 m_notificationStream.postNotification(faceDestroyed);
675}
676
677
678void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600679FaceManager::listFaces(const Interest& request)
680{
681 const Name& command = request.getName();
682 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700683
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600684 if (commandNComps < LIST_COMMAND_NCOMPS ||
685 !LIST_COMMAND_PREFIX.isPrefixOf(command))
686 {
687 NFD_LOG_INFO("command result: malformed");
688 sendResponse(command, 400, "Malformed command");
689 return;
690 }
691
692 m_statusPublisher.publish();
693}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700694
695} // namespace nfd