blob: 183af17648894c8b7dea3afdb761b2fd1028f166 [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"
Junxiao Shi6e694322014-04-03 10:27:13 -07008#include "face-flags.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07009
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060010#include "core/logger.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070011#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060012#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070013#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070014#include "face/tcp-factory.hpp"
15#include "face/udp-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060016
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060017#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
18
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060019#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070020#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060021#endif // HAVE_UNIX_SOCKETS
22
23#ifdef HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070024#include "face/ethernet-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060025#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070026
27namespace nfd {
28
29NFD_LOG_INIT("FaceManager");
30
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060031const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070032
33const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
34 FaceManager::COMMAND_PREFIX.size() +
35 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060036 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037
38const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
39 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070040 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060042const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060044 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060045 Name::Component("create"),
46 &FaceManager::createFace
47 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070048
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060049 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060050 Name::Component("destroy"),
51 &FaceManager::destroyFace
52 ),
53
54 SignedVerbAndProcessor(
55 Name::Component("enable-local-control"),
56 &FaceManager::enableLocalControl
57 ),
58
59 SignedVerbAndProcessor(
60 Name::Component("disable-local-control"),
61 &FaceManager::disableLocalControl
62 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070063 };
64
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060065const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
66 {
67 UnsignedVerbAndProcessor(
68 Name::Component("list"),
69 &FaceManager::listFaces
70 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060071
72 UnsignedVerbAndProcessor(
73 Name::Component("events"),
74 &FaceManager::ignoreUnsignedVerb
75 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060076 };
77
78const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
79const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
80
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060081const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070082
83FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070084 shared_ptr<InternalFace> face)
85 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070086 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060087 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060088 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060089 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060090 SIGNED_COMMAND_VERBS +
91 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060092 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060093 UNSIGNED_COMMAND_VERBS +
94 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060095
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070096{
97 face->setInterestFilter("/localhost/nfd/faces",
98 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060099
100 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
101 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700102}
103
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600104FaceManager::~FaceManager()
105{
106
107}
108
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700109void
110FaceManager::setConfigFile(ConfigFile& configFile)
111{
112 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600113 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700114}
115
116
117void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600118FaceManager::onConfig(const ConfigSection& configSection,
119 bool isDryRun,
120 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700121{
122 bool hasSeenUnix = false;
123 bool hasSeenTcp = false;
124 bool hasSeenUdp = false;
125 bool hasSeenEther = false;
126
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600127 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
128
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700129 for (ConfigSection::const_iterator item = configSection.begin();
130 item != configSection.end();
131 ++item)
132 {
133 if (item->first == "unix")
134 {
135 if (hasSeenUnix)
136 throw Error("Duplicate \"unix\" section");
137 hasSeenUnix = true;
138
139 processSectionUnix(item->second, isDryRun);
140 }
141 else if (item->first == "tcp")
142 {
143 if (hasSeenTcp)
144 throw Error("Duplicate \"tcp\" section");
145 hasSeenTcp = true;
146
147 processSectionTcp(item->second, isDryRun);
148 }
149 else if (item->first == "udp")
150 {
151 if (hasSeenUdp)
152 throw Error("Duplicate \"udp\" section");
153 hasSeenUdp = true;
154
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600155 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700156 }
157 else if (item->first == "ether")
158 {
159 if (hasSeenEther)
160 throw Error("Duplicate \"ether\" section");
161 hasSeenEther = true;
162
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600163 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700164 }
165 else
166 {
167 throw Error("Unrecognized option \"" + item->first + "\"");
168 }
169 }
170}
171
172void
173FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
174{
175 // ; the unix section contains settings of UNIX stream faces and channels
176 // unix
177 // {
178 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
179 // path /var/run/nfd.sock ; UNIX stream listener path
180 // }
181
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600182#if defined(HAVE_UNIX_SOCKETS)
183
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700184 bool needToListen = true;
185 std::string path = "/var/run/nfd.sock";
186
187 for (ConfigSection::const_iterator i = configSection.begin();
188 i != configSection.end();
189 ++i)
190 {
191 if (i->first == "path")
192 {
193 path = i->second.get_value<std::string>();
194 }
195 else if (i->first == "listen")
196 {
197 needToListen = parseYesNo(i, i->first, "unix");
198 }
199 else
200 {
201 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
202 }
203 }
204
205 if (!isDryRun)
206 {
207 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
208 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
209
210 if (needToListen)
211 {
212 // Should acceptFailed callback be used somehow?
213 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
214 UnixStreamChannel::ConnectFailedCallback());
215 }
216
217 m_factories.insert(std::make_pair("unix", factory));
218 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600219#else
220 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
221#endif // HAVE_UNIX_SOCKETS
222
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700223}
224
225void
226FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
227{
228 // ; the tcp section contains settings of TCP faces and channels
229 // tcp
230 // {
231 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
232 // port 6363 ; TCP listener port number
233 // }
234
235 std::string port = "6363";
236 bool needToListen = true;
237
238 for (ConfigSection::const_iterator i = configSection.begin();
239 i != configSection.end();
240 ++i)
241 {
242 if (i->first == "port")
243 {
244 port = i->second.get_value<std::string>();
245 }
246 else if (i->first == "listen")
247 {
248 needToListen = parseYesNo(i, i->first, "tcp");
249 }
250 else
251 {
252 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
253 }
254 }
255
256 if (!isDryRun)
257 {
258 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
259
260 using namespace boost::asio::ip;
261
262 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
263 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
264
265 if (needToListen)
266 {
267 // Should acceptFailed callback be used somehow?
268
269 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
270 TcpChannel::ConnectFailedCallback());
271 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
272 TcpChannel::ConnectFailedCallback());
273 }
274
275 m_factories.insert(std::make_pair("tcp", factory));
276 m_factories.insert(std::make_pair("tcp4", factory));
277 m_factories.insert(std::make_pair("tcp6", factory));
278 }
279}
280
281void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600282FaceManager::processSectionUdp(const ConfigSection& configSection,
283 bool isDryRun,
284 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700285{
286 // ; the udp section contains settings of UDP faces and channels
287 // udp
288 // {
289 // port 6363 ; UDP unicast port number
290 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
291 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
292
293 // ; NFD creates one UDP multicast face per NIC
294 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
295 // mcast_port 56363 ; UDP multicast port number
296 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
297 // }
298
299 std::string port = "6363";
300 size_t timeout = 30;
301 size_t keepAliveInterval = 25;
302 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600303 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700304 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600305
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700306
307 for (ConfigSection::const_iterator i = configSection.begin();
308 i != configSection.end();
309 ++i)
310 {
311 if (i->first == "port")
312 {
313 port = i->second.get_value<std::string>();
314 }
315 else if (i->first == "idle_timeout")
316 {
317 try
318 {
319 timeout = 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 == "keep_alive_interval")
328 {
329 try
330 {
331 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700332
333 /// \todo Make use of keepAliveInterval
334 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700335 }
336 catch (const std::exception& e)
337 {
338 throw ConfigFile::Error("Invalid value for option \"" +
339 i->first + "\" in \"udp\" section");
340 }
341 }
342 else if (i->first == "mcast")
343 {
344 useMcast = parseYesNo(i, i->first, "udp");
345 }
346 else if (i->first == "mcast_port")
347 {
348 mcastPort = i->second.get_value<std::string>();
349 }
350 else if (i->first == "mcast_group")
351 {
352 using namespace boost::asio::ip;
353 mcastGroup = i->second.get_value<std::string>();
354 try
355 {
356 address mcastGroupTest = address::from_string(mcastGroup);
357 if (!mcastGroupTest.is_v4())
358 {
359 throw ConfigFile::Error("Invalid value for option \"" +
360 i->first + "\" in \"udp\" section");
361 }
362 }
363 catch(const std::runtime_error& e)
364 {
365 throw ConfigFile::Error("Invalid value for option \"" +
366 i->first + "\" in \"udp\" section");
367 }
368 }
369 else
370 {
371 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
372 }
373 }
374
375 /// \todo what is keep alive interval used for?
376
377 if (!isDryRun)
378 {
379 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
380
Steve DiBenedettob9906cf2014-03-27 09:18:28 -0600381 shared_ptr<UdpChannel> v4Channel =
382 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
383
384 shared_ptr<UdpChannel> v6Channel =
385 factory->createChannel("::", port, time::seconds(timeout));
386
387 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
388 UdpChannel::ConnectFailedCallback());
389
390 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
391 UdpChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700392
393 m_factories.insert(std::make_pair("udp", factory));
394 m_factories.insert(std::make_pair("udp4", factory));
395 m_factories.insert(std::make_pair("udp6", factory));
396
397 if (useMcast)
398 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600399 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
400 i != nicList.end();
401 ++i)
402 {
403 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
404 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
405 {
406 shared_ptr<MulticastUdpFace> newFace =
407 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
408 mcastGroup, mcastPort);
409
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700410 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600411 }
412 }
413 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700414 }
415}
416
417void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600418FaceManager::processSectionEther(const ConfigSection& configSection,
419 bool isDryRun,
420 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700421{
422 // ; the ether section contains settings of Ethernet faces and channels
423 // ether
424 // {
425 // ; NFD creates one Ethernet multicast face per NIC
426 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
427 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
428 // }
429
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600430#if defined(HAVE_PCAP)
431
432 using ethernet::Address;
433
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700434 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600435 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700436
437 for (ConfigSection::const_iterator i = configSection.begin();
438 i != configSection.end();
439 ++i)
440 {
441 if (i->first == "mcast")
442 {
443 useMcast = parseYesNo(i, i->first, "ether");
444 }
445
446 else if (i->first == "mcast_group")
447 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600448 mcastGroup = Address::fromString(i->second.get_value<std::string>());
449 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700450 {
451 throw ConfigFile::Error("Invalid value for option \"" +
452 i->first + "\" in \"ether\" section");
453 }
454 }
455 else
456 {
457 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
458 }
459 }
460
461 if (!isDryRun)
462 {
463 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
464 m_factories.insert(std::make_pair("ether", factory));
465
466 if (useMcast)
467 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600468 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
469 i != nicList.end();
470 ++i)
471 {
472 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
473 if (nic->isUp() && nic->isMulticastCapable())
474 {
475 try
476 {
477 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100478 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700479
480 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600481 }
482 catch (const EthernetFactory::Error& factoryError)
483 {
484 NFD_LOG_ERROR(factoryError.what() << ", continuing");
485 }
486 catch (const EthernetFace::Error& faceError)
487 {
488 NFD_LOG_ERROR(faceError.what() << ", continuing");
489 }
490 }
491 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700492 }
493 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600494#else
495 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
496#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700497}
498
499
500void
501FaceManager::onFaceRequest(const Interest& request)
502{
503 const Name& command = request.getName();
504 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600505 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700506
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600507 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
508 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
509 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700510 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600511 (unsignedVerbProcessor->second)(this, boost::cref(request));
512 }
513 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600514 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700515 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700516 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700517 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700518 }
519 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
520 !COMMAND_PREFIX.isPrefixOf(command))
521 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700522 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700523 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700524 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600525 else
526 {
527 validate(request,
528 bind(&FaceManager::onValidatedFaceRequest, this, _1),
529 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
530 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700531}
532
533void
534FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
535{
536 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600537 const Name::Component& verb = command[COMMAND_PREFIX.size()];
538 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700539
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600540 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
541 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700542 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600543 ControlParameters parameters;
544 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700545 {
546 sendResponse(command, 400, "Malformed command");
547 return;
548 }
549
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700550 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600551 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700552 }
553 else
554 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700555 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700556 sendResponse(command, 501, "Unsupported command");
557 }
558
559}
560
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700561void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700562FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
563{
564 m_faceTable.add(newFace);
565
Junxiao Shi6e694322014-04-03 10:27:13 -0700566 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700567}
568
569void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700570FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600571 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700572 const shared_ptr<Face>& newFace)
573{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700574 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600575 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700576
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600577 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700578}
579
580void
581FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
582{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700583 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700584 sendResponse(requestName, 400, "Failed to create face");
585}
586
587void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600588FaceManager::createFace(const Interest& request,
589 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700590{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600591 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600592 ndn::nfd::FaceCreateCommand command;
593
594 if (!validateParameters(command, parameters))
595 {
596 sendResponse(requestName, 400, "Malformed command");
597 return;
598 }
599
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700600 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600601 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700602 {
603 sendResponse(requestName, 400, "Malformed command");
604 return;
605 }
606
607 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
608 if (factory == m_factories.end())
609 {
610 sendResponse(requestName, 501, "Unsupported protocol");
611 return;
612 }
613
614 factory->second->createFace(uri,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600615 bind(&FaceManager::onCreated, this, requestName, parameters, _1),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700616 bind(&FaceManager::onConnectFailed, this, requestName, _1));
617}
618
619
620void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600621FaceManager::destroyFace(const Interest& request,
622 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700623{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600624 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600625 ndn::nfd::FaceDestroyCommand command;
626
627 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600628 {
629 sendResponse(requestName, 400, "Malformed command");
630 return;
631 }
632
633 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600634 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700635 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700636 target->close();
637 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600638
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600639 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600640
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700641}
642
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600643void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600644FaceManager::onAddFace(shared_ptr<Face> face)
645{
Junxiao Shi6e694322014-04-03 10:27:13 -0700646 ndn::nfd::FaceEventNotification notification;
647 notification.setKind(ndn::nfd::FACE_EVENT_CREATED)
648 .setFaceId(face->getId())
649 .setRemoteUri(face->getRemoteUri().toString())
650 .setLocalUri(face->getLocalUri().toString())
651 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600652
Junxiao Shi6e694322014-04-03 10:27:13 -0700653 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600654}
655
656void
657FaceManager::onRemoveFace(shared_ptr<Face> face)
658{
Junxiao Shi6e694322014-04-03 10:27:13 -0700659 ndn::nfd::FaceEventNotification notification;
660 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
661 .setFaceId(face->getId())
662 .setRemoteUri(face->getRemoteUri().toString())
663 .setLocalUri(face->getLocalUri().toString())
664 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600665
Junxiao Shi6e694322014-04-03 10:27:13 -0700666 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600667}
668
669
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600670bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600671FaceManager::extractLocalControlParameters(const Interest& request,
672 ControlParameters& parameters,
673 ControlCommand& command,
674 shared_ptr<LocalFace>& outFace,
675 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600676{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600677 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600678 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600679 sendResponse(request.getName(), 400, "Malformed command");
680 return false;
681 }
682
683 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
684
685 if (!static_cast<bool>(face))
686 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700687 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600688 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600689 return false;
690 }
691 else if (!face->isLocal())
692 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700693 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
694 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600695 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600696 return false;
697 }
698
699 outFace = dynamic_pointer_cast<LocalFace>(face);
700 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
701
702 return true;
703}
704
705void
706FaceManager::enableLocalControl(const Interest& request,
707 ControlParameters& parameters)
708{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600709 ndn::nfd::FaceEnableLocalControlCommand command;
710
711
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600712 shared_ptr<LocalFace> face;
713 LocalControlFeature feature;
714
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600715 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600716 {
717 face->setLocalControlHeaderFeature(feature, true);
718 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
719 }
720}
721
722void
723FaceManager::disableLocalControl(const Interest& request,
724 ControlParameters& parameters)
725{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600726 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600727 shared_ptr<LocalFace> face;
728 LocalControlFeature feature;
729
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600730 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600731 {
732 face->setLocalControlHeaderFeature(feature, false);
733 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
734 }
735}
736
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600737void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600738FaceManager::listFaces(const Interest& request)
739{
740 const Name& command = request.getName();
741 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700742
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600743 if (commandNComps < LIST_COMMAND_NCOMPS ||
744 !LIST_COMMAND_PREFIX.isPrefixOf(command))
745 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700746 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600747 sendResponse(command, 400, "Malformed command");
748 return;
749 }
750
751 m_statusPublisher.publish();
752}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700753
754} // namespace nfd