blob: bf31a10de53cdf6f1735acbcbae299b27b83b06c [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
15#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070016#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060017#endif // HAVE_UNIX_SOCKETS
18
19#ifdef HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070020#include "face/ethernet-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060021#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070022
23namespace nfd {
24
25NFD_LOG_INIT("FaceManager");
26
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060027const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070028
29const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
30 FaceManager::COMMAND_PREFIX.size() +
31 1 + // verb
32 1; // verb options
33
34const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
35 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070036 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060038const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070039 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060040 SignedVerbAndProcessor(
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041 Name::Component("create"),
42 &FaceManager::createFace
43 ),
44
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060045 SignedVerbAndProcessor(
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070046 Name::Component("destroy"),
47 &FaceManager::destroyFace
48 ),
49 };
50
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060051const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
52 {
53 UnsignedVerbAndProcessor(
54 Name::Component("list"),
55 &FaceManager::listFaces
56 ),
57 };
58
59const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
60const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
61
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070062
63
64FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070065 shared_ptr<InternalFace> face)
66 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070067 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060068 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
69 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
70 SIGNED_COMMAND_VERBS +
71 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
72 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
73 UNSIGNED_COMMAND_VERBS +
74 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
75
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070076{
77 face->setInterestFilter("/localhost/nfd/faces",
78 bind(&FaceManager::onFaceRequest, this, _2));
79}
80
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060081FaceManager::~FaceManager()
82{
83
84}
85
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070086void
87FaceManager::setConfigFile(ConfigFile& configFile)
88{
89 configFile.addSectionHandler("face_system",
90 bind(&FaceManager::onConfig, this, _1, _2));
91}
92
93
94void
95FaceManager::onConfig(const ConfigSection& configSection, bool isDryRun)
96{
97 bool hasSeenUnix = false;
98 bool hasSeenTcp = false;
99 bool hasSeenUdp = false;
100 bool hasSeenEther = false;
101
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600102 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
103
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700104 for (ConfigSection::const_iterator item = configSection.begin();
105 item != configSection.end();
106 ++item)
107 {
108 if (item->first == "unix")
109 {
110 if (hasSeenUnix)
111 throw Error("Duplicate \"unix\" section");
112 hasSeenUnix = true;
113
114 processSectionUnix(item->second, isDryRun);
115 }
116 else if (item->first == "tcp")
117 {
118 if (hasSeenTcp)
119 throw Error("Duplicate \"tcp\" section");
120 hasSeenTcp = true;
121
122 processSectionTcp(item->second, isDryRun);
123 }
124 else if (item->first == "udp")
125 {
126 if (hasSeenUdp)
127 throw Error("Duplicate \"udp\" section");
128 hasSeenUdp = true;
129
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600130 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700131 }
132 else if (item->first == "ether")
133 {
134 if (hasSeenEther)
135 throw Error("Duplicate \"ether\" section");
136 hasSeenEther = true;
137
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600138 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700139 }
140 else
141 {
142 throw Error("Unrecognized option \"" + item->first + "\"");
143 }
144 }
145}
146
147void
148FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
149{
150 // ; the unix section contains settings of UNIX stream faces and channels
151 // unix
152 // {
153 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
154 // path /var/run/nfd.sock ; UNIX stream listener path
155 // }
156
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600157#if defined(HAVE_UNIX_SOCKETS)
158
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700159 bool needToListen = true;
160 std::string path = "/var/run/nfd.sock";
161
162 for (ConfigSection::const_iterator i = configSection.begin();
163 i != configSection.end();
164 ++i)
165 {
166 if (i->first == "path")
167 {
168 path = i->second.get_value<std::string>();
169 }
170 else if (i->first == "listen")
171 {
172 needToListen = parseYesNo(i, i->first, "unix");
173 }
174 else
175 {
176 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
177 }
178 }
179
180 if (!isDryRun)
181 {
182 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
183 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
184
185 if (needToListen)
186 {
187 // Should acceptFailed callback be used somehow?
188 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
189 UnixStreamChannel::ConnectFailedCallback());
190 }
191
192 m_factories.insert(std::make_pair("unix", factory));
193 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600194#else
195 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
196#endif // HAVE_UNIX_SOCKETS
197
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700198}
199
200void
201FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
202{
203 // ; the tcp section contains settings of TCP faces and channels
204 // tcp
205 // {
206 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
207 // port 6363 ; TCP listener port number
208 // }
209
210 std::string port = "6363";
211 bool needToListen = true;
212
213 for (ConfigSection::const_iterator i = configSection.begin();
214 i != configSection.end();
215 ++i)
216 {
217 if (i->first == "port")
218 {
219 port = i->second.get_value<std::string>();
220 }
221 else if (i->first == "listen")
222 {
223 needToListen = parseYesNo(i, i->first, "tcp");
224 }
225 else
226 {
227 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
228 }
229 }
230
231 if (!isDryRun)
232 {
233 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
234
235 using namespace boost::asio::ip;
236
237 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
238 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
239
240 if (needToListen)
241 {
242 // Should acceptFailed callback be used somehow?
243
244 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
245 TcpChannel::ConnectFailedCallback());
246 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
247 TcpChannel::ConnectFailedCallback());
248 }
249
250 m_factories.insert(std::make_pair("tcp", factory));
251 m_factories.insert(std::make_pair("tcp4", factory));
252 m_factories.insert(std::make_pair("tcp6", factory));
253 }
254}
255
256void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600257FaceManager::processSectionUdp(const ConfigSection& configSection,
258 bool isDryRun,
259 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700260{
261 // ; the udp section contains settings of UDP faces and channels
262 // udp
263 // {
264 // port 6363 ; UDP unicast port number
265 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
266 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
267
268 // ; NFD creates one UDP multicast face per NIC
269 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
270 // mcast_port 56363 ; UDP multicast port number
271 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
272 // }
273
274 std::string port = "6363";
275 size_t timeout = 30;
276 size_t keepAliveInterval = 25;
277 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600278 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700279 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600280
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700281
282 for (ConfigSection::const_iterator i = configSection.begin();
283 i != configSection.end();
284 ++i)
285 {
286 if (i->first == "port")
287 {
288 port = i->second.get_value<std::string>();
289 }
290 else if (i->first == "idle_timeout")
291 {
292 try
293 {
294 timeout = i->second.get_value<size_t>();
295 }
296 catch (const std::exception& e)
297 {
298 throw ConfigFile::Error("Invalid value for option \"" +
299 i->first + "\" in \"udp\" section");
300 }
301 }
302 else if (i->first == "keep_alive_interval")
303 {
304 try
305 {
306 keepAliveInterval = i->second.get_value<size_t>();
307 }
308 catch (const std::exception& e)
309 {
310 throw ConfigFile::Error("Invalid value for option \"" +
311 i->first + "\" in \"udp\" section");
312 }
313 }
314 else if (i->first == "mcast")
315 {
316 useMcast = parseYesNo(i, i->first, "udp");
317 }
318 else if (i->first == "mcast_port")
319 {
320 mcastPort = i->second.get_value<std::string>();
321 }
322 else if (i->first == "mcast_group")
323 {
324 using namespace boost::asio::ip;
325 mcastGroup = i->second.get_value<std::string>();
326 try
327 {
328 address mcastGroupTest = address::from_string(mcastGroup);
329 if (!mcastGroupTest.is_v4())
330 {
331 throw ConfigFile::Error("Invalid value for option \"" +
332 i->first + "\" in \"udp\" section");
333 }
334 }
335 catch(const std::runtime_error& e)
336 {
337 throw ConfigFile::Error("Invalid value for option \"" +
338 i->first + "\" in \"udp\" section");
339 }
340 }
341 else
342 {
343 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
344 }
345 }
346
347 /// \todo what is keep alive interval used for?
348
349 if (!isDryRun)
350 {
351 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
352
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600353 factory->createChannel("::", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700354
355 m_factories.insert(std::make_pair("udp", factory));
356 m_factories.insert(std::make_pair("udp4", factory));
357 m_factories.insert(std::make_pair("udp6", factory));
358
359 if (useMcast)
360 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600361 bool useEndpoint = false;
362 udp::Endpoint localEndpoint;
363
364 try
365 {
366 localEndpoint.port(boost::lexical_cast<uint16_t>(port));
367 useEndpoint = true;
368 }
369 catch (const boost::bad_lexical_cast& error)
370 {
371 NFD_LOG_DEBUG("Treating UDP port \"" << port << "\" as a service name");
372 }
373
374 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
375 i != nicList.end();
376 ++i)
377 {
378 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
379 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
380 {
381 shared_ptr<MulticastUdpFace> newFace =
382 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
383 mcastGroup, mcastPort);
384
385 NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
386
387 if (useEndpoint)
388 {
389 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
390 nic->ipv4Addresses.begin();
391 j != nic->ipv4Addresses.end();
392 ++j)
393 {
394 localEndpoint.address(*j);
395 factory->createChannel(localEndpoint, time::seconds(timeout));
396 }
397 }
398 else
399 {
400 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
401 nic->ipv4Addresses.begin();
402 j != nic->ipv4Addresses.end();
403 ++j)
404 {
405 factory->createChannel(j->to_string(), port, time::seconds(timeout));
406 }
407 }
408 }
409 }
410 }
411 else
412 {
413 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700414 }
415 }
416}
417
418void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600419FaceManager::processSectionEther(const ConfigSection& configSection,
420 bool isDryRun,
421 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700422{
423 // ; the ether section contains settings of Ethernet faces and channels
424 // ether
425 // {
426 // ; NFD creates one Ethernet multicast face per NIC
427 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
428 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
429 // }
430
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600431#if defined(HAVE_PCAP)
432
433 using ethernet::Address;
434
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700435 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600436 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700437
438 for (ConfigSection::const_iterator i = configSection.begin();
439 i != configSection.end();
440 ++i)
441 {
442 if (i->first == "mcast")
443 {
444 useMcast = parseYesNo(i, i->first, "ether");
445 }
446
447 else if (i->first == "mcast_group")
448 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600449 mcastGroup = Address::fromString(i->second.get_value<std::string>());
450 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700451 {
452 throw ConfigFile::Error("Invalid value for option \"" +
453 i->first + "\" in \"ether\" section");
454 }
455 }
456 else
457 {
458 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
459 }
460 }
461
462 if (!isDryRun)
463 {
464 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
465 m_factories.insert(std::make_pair("ether", factory));
466
467 if (useMcast)
468 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600469 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
470 i != nicList.end();
471 ++i)
472 {
473 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
474 if (nic->isUp() && nic->isMulticastCapable())
475 {
476 try
477 {
478 shared_ptr<EthernetFace> newFace =
479 factory->createMulticastFace(nic->name, mcastGroup);
480 NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
481 }
482 catch (const EthernetFactory::Error& factoryError)
483 {
484 NFD_LOG_ERROR(factoryError.what() << ", continuing");
485 }
486 catch (const EthernetFace::Error& faceError)
487 {
488 NFD_LOG_ERROR(faceError.what() << ", continuing");
489 }
490 }
491 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700492 }
493 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600494#else
495 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
496#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700497}
498
499
500void
501FaceManager::onFaceRequest(const Interest& request)
502{
503 const Name& command = request.getName();
504 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600505 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700506
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600507 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
508 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
509 {
510 NFD_LOG_INFO("command result: processing verb: " << verb);
511 (unsignedVerbProcessor->second)(this, boost::cref(request));
512 }
513 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700514 commandNComps < COMMAND_SIGNED_NCOMPS)
515 {
516 NFD_LOG_INFO("command result: unsigned verb: " << command);
517 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700518 }
519 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
520 !COMMAND_PREFIX.isPrefixOf(command))
521 {
522 NFD_LOG_INFO("command result: malformed");
523 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700524 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600525 else
526 {
527 validate(request,
528 bind(&FaceManager::onValidatedFaceRequest, this, _1),
529 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
530 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700531}
532
533void
534FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
535{
536 const Name& command = request->getName();
537 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
538
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600539 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
540 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700541 {
542 ndn::nfd::FaceManagementOptions options;
543 if (!extractOptions(*request, options))
544 {
545 sendResponse(command, 400, "Malformed command");
546 return;
547 }
548
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700549 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600550 (signedVerbProcessor->second)(this, command, options);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700551 }
552 else
553 {
554 NFD_LOG_INFO("command result: unsupported verb: " << verb);
555 sendResponse(command, 501, "Unsupported command");
556 }
557
558}
559
560bool
561FaceManager::extractOptions(const Interest& request,
562 ndn::nfd::FaceManagementOptions& extractedOptions)
563{
564 const Name& command = request.getName();
565 const size_t optionCompIndex =
566 COMMAND_PREFIX.size() + 1;
567
568 try
569 {
570 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
571 extractedOptions.wireDecode(rawOptions);
572 }
573 catch (const ndn::Tlv::Error& e)
574 {
575 NFD_LOG_INFO("Bad command option parse: " << command);
576 return false;
577 }
578 NFD_LOG_DEBUG("Options parsed OK");
579 return true;
580}
581
582void
583FaceManager::onCreated(const Name& requestName,
584 ndn::nfd::FaceManagementOptions& options,
585 const shared_ptr<Face>& newFace)
586{
587 m_faceTable.add(newFace);
588 options.setFaceId(newFace->getId());
589
590 NFD_LOG_INFO("Created Face ID " << newFace->getId());
591
592 ndn::nfd::ControlResponse response;
593 setResponse(response, 200, "Success", options.wireEncode());
594 sendResponse(requestName, response);
595}
596
597void
598FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
599{
600 NFD_LOG_INFO("Failed to create face: " << reason);
601 sendResponse(requestName, 400, "Failed to create face");
602}
603
604void
605FaceManager::createFace(const Name& requestName,
606 ndn::nfd::FaceManagementOptions& options)
607{
608 FaceUri uri;
609 if (!uri.parse(options.getUri()))
610 {
611 sendResponse(requestName, 400, "Malformed command");
612 return;
613 }
614
615 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
616 if (factory == m_factories.end())
617 {
618 sendResponse(requestName, 501, "Unsupported protocol");
619 return;
620 }
621
622 factory->second->createFace(uri,
623 bind(&FaceManager::onCreated, this, requestName, options, _1),
624 bind(&FaceManager::onConnectFailed, this, requestName, _1));
625}
626
627
628void
629FaceManager::destroyFace(const Name& requestName,
630 ndn::nfd::FaceManagementOptions& options)
631{
632 shared_ptr<Face> target = m_faceTable.get(options.getFaceId());
633 if (target)
634 {
635 m_faceTable.remove(target);
636 target->close();
637 }
638 sendResponse(requestName, 200, "Success");
639}
640
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600641void
642FaceManager::listFaces(const Interest& request)
643{
644 const Name& command = request.getName();
645 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700646
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600647 if (commandNComps < LIST_COMMAND_NCOMPS ||
648 !LIST_COMMAND_PREFIX.isPrefixOf(command))
649 {
650 NFD_LOG_INFO("command result: malformed");
651 sendResponse(command, 400, "Malformed command");
652 return;
653 }
654
655 m_statusPublisher.publish();
656}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700657
658} // namespace nfd