blob: 039270f0ef954cf31a1372c879352fcbc265dcce [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
Steve DiBenedetto7564d972014-03-24 14:28:46 -060034 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070035
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 DiBenedetto7564d972014-03-24 14:28:46 -060043 Name::Component("create"),
44 &FaceManager::createFace
45 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070046
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060047 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060048 Name::Component("destroy"),
49 &FaceManager::destroyFace
50 ),
51
52 SignedVerbAndProcessor(
53 Name::Component("enable-local-control"),
54 &FaceManager::enableLocalControl
55 ),
56
57 SignedVerbAndProcessor(
58 Name::Component("disable-local-control"),
59 &FaceManager::disableLocalControl
60 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070061 };
62
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060063const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
64 {
65 UnsignedVerbAndProcessor(
66 Name::Component("list"),
67 &FaceManager::listFaces
68 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060069
70 UnsignedVerbAndProcessor(
71 Name::Component("events"),
72 &FaceManager::ignoreUnsignedVerb
73 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060074 };
75
76const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
77const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
78
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060079const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070080
81FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070082 shared_ptr<InternalFace> face)
83 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070084 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060085 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060086 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060087 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060088 SIGNED_COMMAND_VERBS +
89 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060090 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060091 UNSIGNED_COMMAND_VERBS +
92 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060093
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070094{
95 face->setInterestFilter("/localhost/nfd/faces",
96 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060097
98 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
99 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700100}
101
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600102FaceManager::~FaceManager()
103{
104
105}
106
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700107void
108FaceManager::setConfigFile(ConfigFile& configFile)
109{
110 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600111 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700112}
113
114
115void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600116FaceManager::onConfig(const ConfigSection& configSection,
117 bool isDryRun,
118 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700119{
120 bool hasSeenUnix = false;
121 bool hasSeenTcp = false;
122 bool hasSeenUdp = false;
123 bool hasSeenEther = false;
124
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600125 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
126
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700127 for (ConfigSection::const_iterator item = configSection.begin();
128 item != configSection.end();
129 ++item)
130 {
131 if (item->first == "unix")
132 {
133 if (hasSeenUnix)
134 throw Error("Duplicate \"unix\" section");
135 hasSeenUnix = true;
136
137 processSectionUnix(item->second, isDryRun);
138 }
139 else if (item->first == "tcp")
140 {
141 if (hasSeenTcp)
142 throw Error("Duplicate \"tcp\" section");
143 hasSeenTcp = true;
144
145 processSectionTcp(item->second, isDryRun);
146 }
147 else if (item->first == "udp")
148 {
149 if (hasSeenUdp)
150 throw Error("Duplicate \"udp\" section");
151 hasSeenUdp = true;
152
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600153 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700154 }
155 else if (item->first == "ether")
156 {
157 if (hasSeenEther)
158 throw Error("Duplicate \"ether\" section");
159 hasSeenEther = true;
160
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600161 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700162 }
163 else
164 {
165 throw Error("Unrecognized option \"" + item->first + "\"");
166 }
167 }
168}
169
170void
171FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
172{
173 // ; the unix section contains settings of UNIX stream faces and channels
174 // unix
175 // {
176 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
177 // path /var/run/nfd.sock ; UNIX stream listener path
178 // }
179
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600180#if defined(HAVE_UNIX_SOCKETS)
181
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700182 bool needToListen = true;
183 std::string path = "/var/run/nfd.sock";
184
185 for (ConfigSection::const_iterator i = configSection.begin();
186 i != configSection.end();
187 ++i)
188 {
189 if (i->first == "path")
190 {
191 path = i->second.get_value<std::string>();
192 }
193 else if (i->first == "listen")
194 {
195 needToListen = parseYesNo(i, i->first, "unix");
196 }
197 else
198 {
199 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
200 }
201 }
202
203 if (!isDryRun)
204 {
205 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
206 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
207
208 if (needToListen)
209 {
210 // Should acceptFailed callback be used somehow?
211 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
212 UnixStreamChannel::ConnectFailedCallback());
213 }
214
215 m_factories.insert(std::make_pair("unix", factory));
216 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600217#else
218 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
219#endif // HAVE_UNIX_SOCKETS
220
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700221}
222
223void
224FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
225{
226 // ; the tcp section contains settings of TCP faces and channels
227 // tcp
228 // {
229 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
230 // port 6363 ; TCP listener port number
231 // }
232
233 std::string port = "6363";
234 bool needToListen = true;
235
236 for (ConfigSection::const_iterator i = configSection.begin();
237 i != configSection.end();
238 ++i)
239 {
240 if (i->first == "port")
241 {
242 port = i->second.get_value<std::string>();
243 }
244 else if (i->first == "listen")
245 {
246 needToListen = parseYesNo(i, i->first, "tcp");
247 }
248 else
249 {
250 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
251 }
252 }
253
254 if (!isDryRun)
255 {
256 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
257
258 using namespace boost::asio::ip;
259
260 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
261 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
262
263 if (needToListen)
264 {
265 // Should acceptFailed callback be used somehow?
266
267 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
268 TcpChannel::ConnectFailedCallback());
269 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
270 TcpChannel::ConnectFailedCallback());
271 }
272
273 m_factories.insert(std::make_pair("tcp", factory));
274 m_factories.insert(std::make_pair("tcp4", factory));
275 m_factories.insert(std::make_pair("tcp6", factory));
276 }
277}
278
279void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600280FaceManager::processSectionUdp(const ConfigSection& configSection,
281 bool isDryRun,
282 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700283{
284 // ; the udp section contains settings of UDP faces and channels
285 // udp
286 // {
287 // port 6363 ; UDP unicast port number
288 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
289 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
290
291 // ; NFD creates one UDP multicast face per NIC
292 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
293 // mcast_port 56363 ; UDP multicast port number
294 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
295 // }
296
297 std::string port = "6363";
298 size_t timeout = 30;
299 size_t keepAliveInterval = 25;
300 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600301 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700302 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600303
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700304
305 for (ConfigSection::const_iterator i = configSection.begin();
306 i != configSection.end();
307 ++i)
308 {
309 if (i->first == "port")
310 {
311 port = i->second.get_value<std::string>();
312 }
313 else if (i->first == "idle_timeout")
314 {
315 try
316 {
317 timeout = i->second.get_value<size_t>();
318 }
319 catch (const std::exception& e)
320 {
321 throw ConfigFile::Error("Invalid value for option \"" +
322 i->first + "\" in \"udp\" section");
323 }
324 }
325 else if (i->first == "keep_alive_interval")
326 {
327 try
328 {
329 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700330
331 /// \todo Make use of keepAliveInterval
332 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700333 }
334 catch (const std::exception& e)
335 {
336 throw ConfigFile::Error("Invalid value for option \"" +
337 i->first + "\" in \"udp\" section");
338 }
339 }
340 else if (i->first == "mcast")
341 {
342 useMcast = parseYesNo(i, i->first, "udp");
343 }
344 else if (i->first == "mcast_port")
345 {
346 mcastPort = i->second.get_value<std::string>();
347 }
348 else if (i->first == "mcast_group")
349 {
350 using namespace boost::asio::ip;
351 mcastGroup = i->second.get_value<std::string>();
352 try
353 {
354 address mcastGroupTest = address::from_string(mcastGroup);
355 if (!mcastGroupTest.is_v4())
356 {
357 throw ConfigFile::Error("Invalid value for option \"" +
358 i->first + "\" in \"udp\" section");
359 }
360 }
361 catch(const std::runtime_error& e)
362 {
363 throw ConfigFile::Error("Invalid value for option \"" +
364 i->first + "\" in \"udp\" section");
365 }
366 }
367 else
368 {
369 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
370 }
371 }
372
373 /// \todo what is keep alive interval used for?
374
375 if (!isDryRun)
376 {
377 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
378
Steve DiBenedettob9906cf2014-03-27 09:18:28 -0600379 shared_ptr<UdpChannel> v4Channel =
380 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
381
382 shared_ptr<UdpChannel> v6Channel =
383 factory->createChannel("::", port, time::seconds(timeout));
384
385 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
386 UdpChannel::ConnectFailedCallback());
387
388 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
389 UdpChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700390
391 m_factories.insert(std::make_pair("udp", factory));
392 m_factories.insert(std::make_pair("udp4", factory));
393 m_factories.insert(std::make_pair("udp6", factory));
394
395 if (useMcast)
396 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600397 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
398 i != nicList.end();
399 ++i)
400 {
401 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
402 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
403 {
404 shared_ptr<MulticastUdpFace> newFace =
405 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
406 mcastGroup, mcastPort);
407
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700408 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600409 }
410 }
411 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700412 }
413}
414
415void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600416FaceManager::processSectionEther(const ConfigSection& configSection,
417 bool isDryRun,
418 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700419{
420 // ; the ether section contains settings of Ethernet faces and channels
421 // ether
422 // {
423 // ; NFD creates one Ethernet multicast face per NIC
424 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
425 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
426 // }
427
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600428#if defined(HAVE_PCAP)
429
430 using ethernet::Address;
431
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700432 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600433 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700434
435 for (ConfigSection::const_iterator i = configSection.begin();
436 i != configSection.end();
437 ++i)
438 {
439 if (i->first == "mcast")
440 {
441 useMcast = parseYesNo(i, i->first, "ether");
442 }
443
444 else if (i->first == "mcast_group")
445 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600446 mcastGroup = Address::fromString(i->second.get_value<std::string>());
447 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700448 {
449 throw ConfigFile::Error("Invalid value for option \"" +
450 i->first + "\" in \"ether\" section");
451 }
452 }
453 else
454 {
455 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
456 }
457 }
458
459 if (!isDryRun)
460 {
461 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
462 m_factories.insert(std::make_pair("ether", factory));
463
464 if (useMcast)
465 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600466 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
467 i != nicList.end();
468 ++i)
469 {
470 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
471 if (nic->isUp() && nic->isMulticastCapable())
472 {
473 try
474 {
475 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100476 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700477
478 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600479 }
480 catch (const EthernetFactory::Error& factoryError)
481 {
482 NFD_LOG_ERROR(factoryError.what() << ", continuing");
483 }
484 catch (const EthernetFace::Error& faceError)
485 {
486 NFD_LOG_ERROR(faceError.what() << ", continuing");
487 }
488 }
489 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700490 }
491 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600492#else
493 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
494#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700495}
496
497
498void
499FaceManager::onFaceRequest(const Interest& request)
500{
501 const Name& command = request.getName();
502 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600503 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700504
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600505 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
506 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
507 {
508 NFD_LOG_INFO("command result: processing verb: " << verb);
509 (unsignedVerbProcessor->second)(this, boost::cref(request));
510 }
511 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600512 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700513 {
514 NFD_LOG_INFO("command result: unsigned verb: " << command);
515 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700516 }
517 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
518 !COMMAND_PREFIX.isPrefixOf(command))
519 {
520 NFD_LOG_INFO("command result: malformed");
521 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700522 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600523 else
524 {
525 validate(request,
526 bind(&FaceManager::onValidatedFaceRequest, this, _1),
527 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
528 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700529}
530
531void
532FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
533{
534 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600535 const Name::Component& verb = command[COMMAND_PREFIX.size()];
536 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700537
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600538 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
539 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700540 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600541 ControlParameters parameters;
542 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700543 {
544 sendResponse(command, 400, "Malformed command");
545 return;
546 }
547
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700548 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600549 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700550 }
551 else
552 {
553 NFD_LOG_INFO("command result: unsupported verb: " << verb);
554 sendResponse(command, 501, "Unsupported command");
555 }
556
557}
558
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700559void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700560FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
561{
562 m_faceTable.add(newFace);
563
564 NFD_LOG_INFO("Created face " << newFace->getUri() << " ID " << newFace->getId());
565}
566
567void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700568FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600569 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700570 const shared_ptr<Face>& newFace)
571{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700572 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600573 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700574
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600575 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700576}
577
578void
579FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
580{
581 NFD_LOG_INFO("Failed to create face: " << reason);
582 sendResponse(requestName, 400, "Failed to create face");
583}
584
585void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600586FaceManager::createFace(const Interest& request,
587 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700588{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600589 const Name& requestName = request.getName();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700590 FaceUri uri;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600591 if (!parameters.hasUri() || !uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700592 {
593 sendResponse(requestName, 400, "Malformed command");
594 return;
595 }
596
597 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
598 if (factory == m_factories.end())
599 {
600 sendResponse(requestName, 501, "Unsupported protocol");
601 return;
602 }
603
604 factory->second->createFace(uri,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600605 bind(&FaceManager::onCreated, this, requestName, parameters, _1),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700606 bind(&FaceManager::onConnectFailed, this, requestName, _1));
607}
608
609
610void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600611FaceManager::destroyFace(const Interest& request,
612 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700613{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600614 const Name& requestName = request.getName();
615 if (!parameters.hasFaceId())
616 {
617 sendResponse(requestName, 400, "Malformed command");
618 return;
619 }
620
621 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600622 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700623 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700624 target->close();
625 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600626
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600627 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700628}
629
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600630void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600631FaceManager::onAddFace(shared_ptr<Face> face)
632{
633 ndn::nfd::FaceEventNotification faceCreated(ndn::nfd::FACE_EVENT_CREATED,
634 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700635 face->getUri().toString(),
636 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
637 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600638
639 m_notificationStream.postNotification(faceCreated);
640}
641
642void
643FaceManager::onRemoveFace(shared_ptr<Face> face)
644{
645 ndn::nfd::FaceEventNotification faceDestroyed(ndn::nfd::FACE_EVENT_DESTROYED,
646 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700647 face->getUri().toString(),
648 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
649 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600650
651 m_notificationStream.postNotification(faceDestroyed);
652}
653
654
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600655bool
656FaceManager::validateLocalControlParameters(const Interest& request,
657 ControlParameters& parameters,
658 shared_ptr<LocalFace>& outFace,
659 LocalControlFeature& outFeature)
660{
661 if (!parameters.hasLocalControlFeature() ||
662 (parameters.getLocalControlFeature() != LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID &&
663 parameters.getLocalControlFeature() != LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID))
664 {
665 NFD_LOG_INFO("command result: malformed");
666 sendResponse(request.getName(), 400, "Malformed command");
667 return false;
668 }
669
670 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
671
672 if (!static_cast<bool>(face))
673 {
674 NFD_LOG_INFO("command result: faceid " << parameters.getFaceId() << " not found");
675 sendResponse(request.getName(), 410, "Requested face not found");
676 return false;
677 }
678 else if (!face->isLocal())
679 {
680 NFD_LOG_INFO("command result: cannot enable local control on non-local faceid " << parameters.getFaceId());
681 sendResponse(request.getName(), 412, "Requested face is non-local");
682 return false;
683 }
684
685 outFace = dynamic_pointer_cast<LocalFace>(face);
686 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
687
688 return true;
689}
690
691void
692FaceManager::enableLocalControl(const Interest& request,
693 ControlParameters& parameters)
694{
695 shared_ptr<LocalFace> face;
696 LocalControlFeature feature;
697
698 if (validateLocalControlParameters(request, parameters, face, feature))
699 {
700 face->setLocalControlHeaderFeature(feature, true);
701 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
702 }
703}
704
705void
706FaceManager::disableLocalControl(const Interest& request,
707 ControlParameters& parameters)
708{
709 shared_ptr<LocalFace> face;
710 LocalControlFeature feature;
711
712 if (validateLocalControlParameters(request, parameters, face, feature))
713 {
714 face->setLocalControlHeaderFeature(feature, false);
715 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
716 }
717}
718
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600719void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600720FaceManager::listFaces(const Interest& request)
721{
722 const Name& command = request.getName();
723 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700724
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600725 if (commandNComps < LIST_COMMAND_NCOMPS ||
726 !LIST_COMMAND_PREFIX.isPrefixOf(command))
727 {
728 NFD_LOG_INFO("command result: malformed");
729 sendResponse(command, 400, "Malformed command");
730 return;
731 }
732
733 m_statusPublisher.publish();
734}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700735
736} // namespace nfd