blob: ea9289818358be5c389f894367f529d645f6caa9 [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 DiBenedetto4aca99c2014-03-11 11:27:54 -0600379 factory->createChannel("::", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700380
381 m_factories.insert(std::make_pair("udp", factory));
382 m_factories.insert(std::make_pair("udp4", factory));
383 m_factories.insert(std::make_pair("udp6", factory));
384
385 if (useMcast)
386 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600387 bool useEndpoint = false;
388 udp::Endpoint localEndpoint;
389
390 try
391 {
392 localEndpoint.port(boost::lexical_cast<uint16_t>(port));
393 useEndpoint = true;
394 }
395 catch (const boost::bad_lexical_cast& error)
396 {
397 NFD_LOG_DEBUG("Treating UDP port \"" << port << "\" as a service name");
398 }
399
400 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
401 i != nicList.end();
402 ++i)
403 {
404 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
405 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
406 {
407 shared_ptr<MulticastUdpFace> newFace =
408 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
409 mcastGroup, mcastPort);
410
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700411 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600412
413 if (useEndpoint)
414 {
415 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
416 nic->ipv4Addresses.begin();
417 j != nic->ipv4Addresses.end();
418 ++j)
419 {
420 localEndpoint.address(*j);
421 factory->createChannel(localEndpoint, time::seconds(timeout));
422 }
423 }
424 else
425 {
426 for (std::vector<boost::asio::ip::address_v4>::const_iterator j =
427 nic->ipv4Addresses.begin();
428 j != nic->ipv4Addresses.end();
429 ++j)
430 {
431 factory->createChannel(j->to_string(), port, time::seconds(timeout));
432 }
433 }
434 }
435 }
436 }
437 else
438 {
439 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700440 }
441 }
442}
443
444void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600445FaceManager::processSectionEther(const ConfigSection& configSection,
446 bool isDryRun,
447 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700448{
449 // ; the ether section contains settings of Ethernet faces and channels
450 // ether
451 // {
452 // ; NFD creates one Ethernet multicast face per NIC
453 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
454 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
455 // }
456
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600457#if defined(HAVE_PCAP)
458
459 using ethernet::Address;
460
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700461 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600462 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700463
464 for (ConfigSection::const_iterator i = configSection.begin();
465 i != configSection.end();
466 ++i)
467 {
468 if (i->first == "mcast")
469 {
470 useMcast = parseYesNo(i, i->first, "ether");
471 }
472
473 else if (i->first == "mcast_group")
474 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600475 mcastGroup = Address::fromString(i->second.get_value<std::string>());
476 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700477 {
478 throw ConfigFile::Error("Invalid value for option \"" +
479 i->first + "\" in \"ether\" section");
480 }
481 }
482 else
483 {
484 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
485 }
486 }
487
488 if (!isDryRun)
489 {
490 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
491 m_factories.insert(std::make_pair("ether", factory));
492
493 if (useMcast)
494 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600495 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
496 i != nicList.end();
497 ++i)
498 {
499 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
500 if (nic->isUp() && nic->isMulticastCapable())
501 {
502 try
503 {
504 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100505 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700506
507 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600508 }
509 catch (const EthernetFactory::Error& factoryError)
510 {
511 NFD_LOG_ERROR(factoryError.what() << ", continuing");
512 }
513 catch (const EthernetFace::Error& faceError)
514 {
515 NFD_LOG_ERROR(faceError.what() << ", continuing");
516 }
517 }
518 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700519 }
520 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600521#else
522 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
523#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700524}
525
526
527void
528FaceManager::onFaceRequest(const Interest& request)
529{
530 const Name& command = request.getName();
531 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600532 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700533
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600534 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
535 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
536 {
537 NFD_LOG_INFO("command result: processing verb: " << verb);
538 (unsignedVerbProcessor->second)(this, boost::cref(request));
539 }
540 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600541 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700542 {
543 NFD_LOG_INFO("command result: unsigned verb: " << command);
544 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700545 }
546 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
547 !COMMAND_PREFIX.isPrefixOf(command))
548 {
549 NFD_LOG_INFO("command result: malformed");
550 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700551 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600552 else
553 {
554 validate(request,
555 bind(&FaceManager::onValidatedFaceRequest, this, _1),
556 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
557 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700558}
559
560void
561FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
562{
563 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600564 const Name::Component& verb = command[COMMAND_PREFIX.size()];
565 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700566
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600567 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
568 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700569 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600570 ControlParameters parameters;
571 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700572 {
573 sendResponse(command, 400, "Malformed command");
574 return;
575 }
576
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700577 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600578 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700579 }
580 else
581 {
582 NFD_LOG_INFO("command result: unsupported verb: " << verb);
583 sendResponse(command, 501, "Unsupported command");
584 }
585
586}
587
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700588void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700589FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
590{
591 m_faceTable.add(newFace);
592
593 NFD_LOG_INFO("Created face " << newFace->getUri() << " ID " << newFace->getId());
594}
595
596void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700597FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600598 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700599 const shared_ptr<Face>& newFace)
600{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700601 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600602 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700603
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600604 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700605}
606
607void
608FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
609{
610 NFD_LOG_INFO("Failed to create face: " << reason);
611 sendResponse(requestName, 400, "Failed to create face");
612}
613
614void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600615FaceManager::createFace(const Interest& request,
616 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700617{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600618 const Name& requestName = request.getName();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700619 FaceUri uri;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600620 if (!parameters.hasUri() || !uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700621 {
622 sendResponse(requestName, 400, "Malformed command");
623 return;
624 }
625
626 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
627 if (factory == m_factories.end())
628 {
629 sendResponse(requestName, 501, "Unsupported protocol");
630 return;
631 }
632
633 factory->second->createFace(uri,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600634 bind(&FaceManager::onCreated, this, requestName, parameters, _1),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700635 bind(&FaceManager::onConnectFailed, this, requestName, _1));
636}
637
638
639void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600640FaceManager::destroyFace(const Interest& request,
641 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700642{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600643 const Name& requestName = request.getName();
644 if (!parameters.hasFaceId())
645 {
646 sendResponse(requestName, 400, "Malformed command");
647 return;
648 }
649
650 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600651 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700652 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700653 target->close();
654 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600655
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600656 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700657}
658
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600659void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600660FaceManager::onAddFace(shared_ptr<Face> face)
661{
662 ndn::nfd::FaceEventNotification faceCreated(ndn::nfd::FACE_EVENT_CREATED,
663 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700664 face->getUri().toString(),
665 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
666 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600667
668 m_notificationStream.postNotification(faceCreated);
669}
670
671void
672FaceManager::onRemoveFace(shared_ptr<Face> face)
673{
674 ndn::nfd::FaceEventNotification faceDestroyed(ndn::nfd::FACE_EVENT_DESTROYED,
675 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700676 face->getUri().toString(),
677 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
678 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600679
680 m_notificationStream.postNotification(faceDestroyed);
681}
682
683
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600684bool
685FaceManager::validateLocalControlParameters(const Interest& request,
686 ControlParameters& parameters,
687 shared_ptr<LocalFace>& outFace,
688 LocalControlFeature& outFeature)
689{
690 if (!parameters.hasLocalControlFeature() ||
691 (parameters.getLocalControlFeature() != LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID &&
692 parameters.getLocalControlFeature() != LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID))
693 {
694 NFD_LOG_INFO("command result: malformed");
695 sendResponse(request.getName(), 400, "Malformed command");
696 return false;
697 }
698
699 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
700
701 if (!static_cast<bool>(face))
702 {
703 NFD_LOG_INFO("command result: faceid " << parameters.getFaceId() << " not found");
704 sendResponse(request.getName(), 410, "Requested face not found");
705 return false;
706 }
707 else if (!face->isLocal())
708 {
709 NFD_LOG_INFO("command result: cannot enable local control on non-local faceid " << parameters.getFaceId());
710 sendResponse(request.getName(), 412, "Requested face is non-local");
711 return false;
712 }
713
714 outFace = dynamic_pointer_cast<LocalFace>(face);
715 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
716
717 return true;
718}
719
720void
721FaceManager::enableLocalControl(const Interest& request,
722 ControlParameters& parameters)
723{
724 shared_ptr<LocalFace> face;
725 LocalControlFeature feature;
726
727 if (validateLocalControlParameters(request, parameters, face, feature))
728 {
729 face->setLocalControlHeaderFeature(feature, true);
730 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
731 }
732}
733
734void
735FaceManager::disableLocalControl(const Interest& request,
736 ControlParameters& parameters)
737{
738 shared_ptr<LocalFace> face;
739 LocalControlFeature feature;
740
741 if (validateLocalControlParameters(request, parameters, face, feature))
742 {
743 face->setLocalControlHeaderFeature(feature, false);
744 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
745 }
746}
747
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600748void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600749FaceManager::listFaces(const Interest& request)
750{
751 const Name& command = request.getName();
752 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700753
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600754 if (commandNComps < LIST_COMMAND_NCOMPS ||
755 !LIST_COMMAND_PREFIX.isPrefixOf(command))
756 {
757 NFD_LOG_INFO("command result: malformed");
758 sendResponse(command, 400, "Malformed command");
759 return;
760 }
761
762 m_statusPublisher.publish();
763}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700764
765} // namespace nfd