blob: 237a91457d298c7ce18950ad186c3706a82a4ab5 [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",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060090 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070091}
92
93
94void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -060095FaceManager::onConfig(const ConfigSection& configSection,
96 bool isDryRun,
97 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070098{
99 bool hasSeenUnix = false;
100 bool hasSeenTcp = false;
101 bool hasSeenUdp = false;
102 bool hasSeenEther = false;
103
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600104 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
105
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700106 for (ConfigSection::const_iterator item = configSection.begin();
107 item != configSection.end();
108 ++item)
109 {
110 if (item->first == "unix")
111 {
112 if (hasSeenUnix)
113 throw Error("Duplicate \"unix\" section");
114 hasSeenUnix = true;
115
116 processSectionUnix(item->second, isDryRun);
117 }
118 else if (item->first == "tcp")
119 {
120 if (hasSeenTcp)
121 throw Error("Duplicate \"tcp\" section");
122 hasSeenTcp = true;
123
124 processSectionTcp(item->second, isDryRun);
125 }
126 else if (item->first == "udp")
127 {
128 if (hasSeenUdp)
129 throw Error("Duplicate \"udp\" section");
130 hasSeenUdp = true;
131
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600132 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700133 }
134 else if (item->first == "ether")
135 {
136 if (hasSeenEther)
137 throw Error("Duplicate \"ether\" section");
138 hasSeenEther = true;
139
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600140 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700141 }
142 else
143 {
144 throw Error("Unrecognized option \"" + item->first + "\"");
145 }
146 }
147}
148
149void
150FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
151{
152 // ; the unix section contains settings of UNIX stream faces and channels
153 // unix
154 // {
155 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
156 // path /var/run/nfd.sock ; UNIX stream listener path
157 // }
158
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600159#if defined(HAVE_UNIX_SOCKETS)
160
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700161 bool needToListen = true;
162 std::string path = "/var/run/nfd.sock";
163
164 for (ConfigSection::const_iterator i = configSection.begin();
165 i != configSection.end();
166 ++i)
167 {
168 if (i->first == "path")
169 {
170 path = i->second.get_value<std::string>();
171 }
172 else if (i->first == "listen")
173 {
174 needToListen = parseYesNo(i, i->first, "unix");
175 }
176 else
177 {
178 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
179 }
180 }
181
182 if (!isDryRun)
183 {
184 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
185 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
186
187 if (needToListen)
188 {
189 // Should acceptFailed callback be used somehow?
190 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
191 UnixStreamChannel::ConnectFailedCallback());
192 }
193
194 m_factories.insert(std::make_pair("unix", factory));
195 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600196#else
197 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
198#endif // HAVE_UNIX_SOCKETS
199
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700200}
201
202void
203FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
204{
205 // ; the tcp section contains settings of TCP faces and channels
206 // tcp
207 // {
208 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
209 // port 6363 ; TCP listener port number
210 // }
211
212 std::string port = "6363";
213 bool needToListen = true;
214
215 for (ConfigSection::const_iterator i = configSection.begin();
216 i != configSection.end();
217 ++i)
218 {
219 if (i->first == "port")
220 {
221 port = i->second.get_value<std::string>();
222 }
223 else if (i->first == "listen")
224 {
225 needToListen = parseYesNo(i, i->first, "tcp");
226 }
227 else
228 {
229 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
230 }
231 }
232
233 if (!isDryRun)
234 {
235 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
236
237 using namespace boost::asio::ip;
238
239 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
240 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
241
242 if (needToListen)
243 {
244 // Should acceptFailed callback be used somehow?
245
246 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
247 TcpChannel::ConnectFailedCallback());
248 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
249 TcpChannel::ConnectFailedCallback());
250 }
251
252 m_factories.insert(std::make_pair("tcp", factory));
253 m_factories.insert(std::make_pair("tcp4", factory));
254 m_factories.insert(std::make_pair("tcp6", factory));
255 }
256}
257
258void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600259FaceManager::processSectionUdp(const ConfigSection& configSection,
260 bool isDryRun,
261 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700262{
263 // ; the udp section contains settings of UDP faces and channels
264 // udp
265 // {
266 // port 6363 ; UDP unicast port number
267 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
268 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
269
270 // ; NFD creates one UDP multicast face per NIC
271 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
272 // mcast_port 56363 ; UDP multicast port number
273 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
274 // }
275
276 std::string port = "6363";
277 size_t timeout = 30;
278 size_t keepAliveInterval = 25;
279 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600280 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700281 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600282
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700283
284 for (ConfigSection::const_iterator i = configSection.begin();
285 i != configSection.end();
286 ++i)
287 {
288 if (i->first == "port")
289 {
290 port = i->second.get_value<std::string>();
291 }
292 else if (i->first == "idle_timeout")
293 {
294 try
295 {
296 timeout = i->second.get_value<size_t>();
297 }
298 catch (const std::exception& e)
299 {
300 throw ConfigFile::Error("Invalid value for option \"" +
301 i->first + "\" in \"udp\" section");
302 }
303 }
304 else if (i->first == "keep_alive_interval")
305 {
306 try
307 {
308 keepAliveInterval = i->second.get_value<size_t>();
309 }
310 catch (const std::exception& e)
311 {
312 throw ConfigFile::Error("Invalid value for option \"" +
313 i->first + "\" in \"udp\" section");
314 }
315 }
316 else if (i->first == "mcast")
317 {
318 useMcast = parseYesNo(i, i->first, "udp");
319 }
320 else if (i->first == "mcast_port")
321 {
322 mcastPort = i->second.get_value<std::string>();
323 }
324 else if (i->first == "mcast_group")
325 {
326 using namespace boost::asio::ip;
327 mcastGroup = i->second.get_value<std::string>();
328 try
329 {
330 address mcastGroupTest = address::from_string(mcastGroup);
331 if (!mcastGroupTest.is_v4())
332 {
333 throw ConfigFile::Error("Invalid value for option \"" +
334 i->first + "\" in \"udp\" section");
335 }
336 }
337 catch(const std::runtime_error& e)
338 {
339 throw ConfigFile::Error("Invalid value for option \"" +
340 i->first + "\" in \"udp\" section");
341 }
342 }
343 else
344 {
345 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
346 }
347 }
348
349 /// \todo what is keep alive interval used for?
350
351 if (!isDryRun)
352 {
353 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
354
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600355 factory->createChannel("::", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700356
357 m_factories.insert(std::make_pair("udp", factory));
358 m_factories.insert(std::make_pair("udp4", factory));
359 m_factories.insert(std::make_pair("udp6", factory));
360
361 if (useMcast)
362 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600363 bool useEndpoint = false;
364 udp::Endpoint localEndpoint;
365
366 try
367 {
368 localEndpoint.port(boost::lexical_cast<uint16_t>(port));
369 useEndpoint = true;
370 }
371 catch (const boost::bad_lexical_cast& error)
372 {
373 NFD_LOG_DEBUG("Treating UDP port \"" << port << "\" as a service name");
374 }
375
376 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
377 i != nicList.end();
378 ++i)
379 {
380 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
381 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
382 {
383 shared_ptr<MulticastUdpFace> newFace =
384 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
385 mcastGroup, mcastPort);
386
387 NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
388
389 if (useEndpoint)
390 {
391 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
392 nic->ipv4Addresses.begin();
393 j != nic->ipv4Addresses.end();
394 ++j)
395 {
396 localEndpoint.address(*j);
397 factory->createChannel(localEndpoint, time::seconds(timeout));
398 }
399 }
400 else
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 factory->createChannel(j->to_string(), port, time::seconds(timeout));
408 }
409 }
410 }
411 }
412 }
413 else
414 {
415 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700416 }
417 }
418}
419
420void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600421FaceManager::processSectionEther(const ConfigSection& configSection,
422 bool isDryRun,
423 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700424{
425 // ; the ether section contains settings of Ethernet faces and channels
426 // ether
427 // {
428 // ; NFD creates one Ethernet multicast face per NIC
429 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
430 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
431 // }
432
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600433#if defined(HAVE_PCAP)
434
435 using ethernet::Address;
436
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700437 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600438 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700439
440 for (ConfigSection::const_iterator i = configSection.begin();
441 i != configSection.end();
442 ++i)
443 {
444 if (i->first == "mcast")
445 {
446 useMcast = parseYesNo(i, i->first, "ether");
447 }
448
449 else if (i->first == "mcast_group")
450 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600451 mcastGroup = Address::fromString(i->second.get_value<std::string>());
452 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700453 {
454 throw ConfigFile::Error("Invalid value for option \"" +
455 i->first + "\" in \"ether\" section");
456 }
457 }
458 else
459 {
460 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
461 }
462 }
463
464 if (!isDryRun)
465 {
466 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
467 m_factories.insert(std::make_pair("ether", factory));
468
469 if (useMcast)
470 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600471 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
472 i != nicList.end();
473 ++i)
474 {
475 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
476 if (nic->isUp() && nic->isMulticastCapable())
477 {
478 try
479 {
480 shared_ptr<EthernetFace> newFace =
481 factory->createMulticastFace(nic->name, mcastGroup);
482 NFD_LOG_INFO("Created multicast Face ID " << newFace->getId());
483 }
484 catch (const EthernetFactory::Error& factoryError)
485 {
486 NFD_LOG_ERROR(factoryError.what() << ", continuing");
487 }
488 catch (const EthernetFace::Error& faceError)
489 {
490 NFD_LOG_ERROR(faceError.what() << ", continuing");
491 }
492 }
493 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700494 }
495 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600496#else
497 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
498#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700499}
500
501
502void
503FaceManager::onFaceRequest(const Interest& request)
504{
505 const Name& command = request.getName();
506 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600507 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700508
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600509 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
510 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
511 {
512 NFD_LOG_INFO("command result: processing verb: " << verb);
513 (unsignedVerbProcessor->second)(this, boost::cref(request));
514 }
515 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700516 commandNComps < COMMAND_SIGNED_NCOMPS)
517 {
518 NFD_LOG_INFO("command result: unsigned verb: " << command);
519 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700520 }
521 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
522 !COMMAND_PREFIX.isPrefixOf(command))
523 {
524 NFD_LOG_INFO("command result: malformed");
525 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700526 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600527 else
528 {
529 validate(request,
530 bind(&FaceManager::onValidatedFaceRequest, this, _1),
531 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
532 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700533}
534
535void
536FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
537{
538 const Name& command = request->getName();
539 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
540
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600541 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
542 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700543 {
544 ndn::nfd::FaceManagementOptions options;
545 if (!extractOptions(*request, options))
546 {
547 sendResponse(command, 400, "Malformed command");
548 return;
549 }
550
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700551 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600552 (signedVerbProcessor->second)(this, command, options);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700553 }
554 else
555 {
556 NFD_LOG_INFO("command result: unsupported verb: " << verb);
557 sendResponse(command, 501, "Unsupported command");
558 }
559
560}
561
562bool
563FaceManager::extractOptions(const Interest& request,
564 ndn::nfd::FaceManagementOptions& extractedOptions)
565{
566 const Name& command = request.getName();
567 const size_t optionCompIndex =
568 COMMAND_PREFIX.size() + 1;
569
570 try
571 {
572 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
573 extractedOptions.wireDecode(rawOptions);
574 }
575 catch (const ndn::Tlv::Error& e)
576 {
577 NFD_LOG_INFO("Bad command option parse: " << command);
578 return false;
579 }
580 NFD_LOG_DEBUG("Options parsed OK");
581 return true;
582}
583
584void
585FaceManager::onCreated(const Name& requestName,
586 ndn::nfd::FaceManagementOptions& options,
587 const shared_ptr<Face>& newFace)
588{
589 m_faceTable.add(newFace);
590 options.setFaceId(newFace->getId());
591
592 NFD_LOG_INFO("Created Face ID " << newFace->getId());
593
594 ndn::nfd::ControlResponse response;
595 setResponse(response, 200, "Success", options.wireEncode());
596 sendResponse(requestName, response);
597}
598
599void
600FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
601{
602 NFD_LOG_INFO("Failed to create face: " << reason);
603 sendResponse(requestName, 400, "Failed to create face");
604}
605
606void
607FaceManager::createFace(const Name& requestName,
608 ndn::nfd::FaceManagementOptions& options)
609{
610 FaceUri uri;
611 if (!uri.parse(options.getUri()))
612 {
613 sendResponse(requestName, 400, "Malformed command");
614 return;
615 }
616
617 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
618 if (factory == m_factories.end())
619 {
620 sendResponse(requestName, 501, "Unsupported protocol");
621 return;
622 }
623
624 factory->second->createFace(uri,
625 bind(&FaceManager::onCreated, this, requestName, options, _1),
626 bind(&FaceManager::onConnectFailed, this, requestName, _1));
627}
628
629
630void
631FaceManager::destroyFace(const Name& requestName,
632 ndn::nfd::FaceManagementOptions& options)
633{
634 shared_ptr<Face> target = m_faceTable.get(options.getFaceId());
635 if (target)
636 {
Junxiao Shic542b2b2014-03-16 21:45:52 -0700637 // don't call m_faceTable.remove(target): it's called by target->close() via onFail
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700638 target->close();
639 }
640 sendResponse(requestName, 200, "Success");
641}
642
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600643void
644FaceManager::listFaces(const Interest& request)
645{
646 const Name& command = request.getName();
647 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700648
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600649 if (commandNComps < LIST_COMMAND_NCOMPS ||
650 !LIST_COMMAND_PREFIX.isPrefixOf(command))
651 {
652 NFD_LOG_INFO("command result: malformed");
653 sendResponse(command, 400, "Malformed command");
654 return;
655 }
656
657 m_statusPublisher.publish();
658}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700659
660} // namespace nfd