blob: 96d1ce73769f254109d0676d527679fab3c1640b [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
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700398 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600399
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);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700493
494 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600495 }
496 catch (const EthernetFactory::Error& factoryError)
497 {
498 NFD_LOG_ERROR(factoryError.what() << ", continuing");
499 }
500 catch (const EthernetFace::Error& faceError)
501 {
502 NFD_LOG_ERROR(faceError.what() << ", continuing");
503 }
504 }
505 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700506 }
507 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600508#else
509 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
510#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700511}
512
513
514void
515FaceManager::onFaceRequest(const Interest& request)
516{
517 const Name& command = request.getName();
518 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600519 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700520
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600521 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
522 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
523 {
524 NFD_LOG_INFO("command result: processing verb: " << verb);
525 (unsignedVerbProcessor->second)(this, boost::cref(request));
526 }
527 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700528 commandNComps < COMMAND_SIGNED_NCOMPS)
529 {
530 NFD_LOG_INFO("command result: unsigned verb: " << command);
531 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700532 }
533 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
534 !COMMAND_PREFIX.isPrefixOf(command))
535 {
536 NFD_LOG_INFO("command result: malformed");
537 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700538 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600539 else
540 {
541 validate(request,
542 bind(&FaceManager::onValidatedFaceRequest, this, _1),
543 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
544 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700545}
546
547void
548FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
549{
550 const Name& command = request->getName();
551 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
552
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600553 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
554 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700555 {
556 ndn::nfd::FaceManagementOptions options;
557 if (!extractOptions(*request, options))
558 {
559 sendResponse(command, 400, "Malformed command");
560 return;
561 }
562
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700563 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600564 (signedVerbProcessor->second)(this, command, options);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700565 }
566 else
567 {
568 NFD_LOG_INFO("command result: unsupported verb: " << verb);
569 sendResponse(command, 501, "Unsupported command");
570 }
571
572}
573
574bool
575FaceManager::extractOptions(const Interest& request,
576 ndn::nfd::FaceManagementOptions& extractedOptions)
577{
578 const Name& command = request.getName();
579 const size_t optionCompIndex =
580 COMMAND_PREFIX.size() + 1;
581
582 try
583 {
584 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
585 extractedOptions.wireDecode(rawOptions);
586 }
587 catch (const ndn::Tlv::Error& e)
588 {
589 NFD_LOG_INFO("Bad command option parse: " << command);
590 return false;
591 }
592 NFD_LOG_DEBUG("Options parsed OK");
593 return true;
594}
595
596void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700597FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
598{
599 m_faceTable.add(newFace);
600
601 NFD_LOG_INFO("Created face " << newFace->getUri() << " ID " << newFace->getId());
602}
603
604void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700605FaceManager::onCreated(const Name& requestName,
606 ndn::nfd::FaceManagementOptions& options,
607 const shared_ptr<Face>& newFace)
608{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700609 addCreatedFaceToForwarder(newFace);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700610
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700611 options.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700612
613 ndn::nfd::ControlResponse response;
614 setResponse(response, 200, "Success", options.wireEncode());
615 sendResponse(requestName, response);
616}
617
618void
619FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
620{
621 NFD_LOG_INFO("Failed to create face: " << reason);
622 sendResponse(requestName, 400, "Failed to create face");
623}
624
625void
626FaceManager::createFace(const Name& requestName,
627 ndn::nfd::FaceManagementOptions& options)
628{
629 FaceUri uri;
630 if (!uri.parse(options.getUri()))
631 {
632 sendResponse(requestName, 400, "Malformed command");
633 return;
634 }
635
636 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
637 if (factory == m_factories.end())
638 {
639 sendResponse(requestName, 501, "Unsupported protocol");
640 return;
641 }
642
643 factory->second->createFace(uri,
644 bind(&FaceManager::onCreated, this, requestName, options, _1),
645 bind(&FaceManager::onConnectFailed, this, requestName, _1));
646}
647
648
649void
650FaceManager::destroyFace(const Name& requestName,
651 ndn::nfd::FaceManagementOptions& options)
652{
653 shared_ptr<Face> target = m_faceTable.get(options.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600654 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700655 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700656 target->close();
657 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600658
659 ndn::nfd::ControlResponse response;
660 setResponse(response, 200, "Success", options.wireEncode());
661 sendResponse(requestName, response);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700662}
663
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600664void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600665FaceManager::onAddFace(shared_ptr<Face> face)
666{
667 ndn::nfd::FaceEventNotification faceCreated(ndn::nfd::FACE_EVENT_CREATED,
668 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700669 face->getUri().toString(),
670 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
671 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600672
673 m_notificationStream.postNotification(faceCreated);
674}
675
676void
677FaceManager::onRemoveFace(shared_ptr<Face> face)
678{
679 ndn::nfd::FaceEventNotification faceDestroyed(ndn::nfd::FACE_EVENT_DESTROYED,
680 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700681 face->getUri().toString(),
682 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
683 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600684
685 m_notificationStream.postNotification(faceDestroyed);
686}
687
688
689void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600690FaceManager::listFaces(const Interest& request)
691{
692 const Name& command = request.getName();
693 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700694
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600695 if (commandNComps < LIST_COMMAND_NCOMPS ||
696 !LIST_COMMAND_PREFIX.isPrefixOf(command))
697 {
698 NFD_LOG_INFO("command result: malformed");
699 sendResponse(command, 400, "Malformed command");
700 return;
701 }
702
703 m_statusPublisher.publish();
704}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700705
706} // namespace nfd