blob: 55f4d9cd2125c3789b4fa94e9b47fc1298043e8a [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
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -06009#include "core/logger.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070010#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060011#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070012#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070013#include "face/tcp-factory.hpp"
14#include "face/udp-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060015
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060016#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
17
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060018#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070019#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060020#endif // HAVE_UNIX_SOCKETS
21
22#ifdef HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070023#include "face/ethernet-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060024#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070025
26namespace nfd {
27
28NFD_LOG_INIT("FaceManager");
29
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060030const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070031
32const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
33 FaceManager::COMMAND_PREFIX.size() +
34 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060035 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070036
37const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
38 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070039 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070040
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060041const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070042 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060043 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060044 Name::Component("create"),
45 &FaceManager::createFace
46 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070047
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060048 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060049 Name::Component("destroy"),
50 &FaceManager::destroyFace
51 ),
52
53 SignedVerbAndProcessor(
54 Name::Component("enable-local-control"),
55 &FaceManager::enableLocalControl
56 ),
57
58 SignedVerbAndProcessor(
59 Name::Component("disable-local-control"),
60 &FaceManager::disableLocalControl
61 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070062 };
63
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060064const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
65 {
66 UnsignedVerbAndProcessor(
67 Name::Component("list"),
68 &FaceManager::listFaces
69 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060070
71 UnsignedVerbAndProcessor(
72 Name::Component("events"),
73 &FaceManager::ignoreUnsignedVerb
74 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060075 };
76
77const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
78const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
79
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060080const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070081
82FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070083 shared_ptr<InternalFace> face)
84 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070085 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060086 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060087 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060088 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060089 SIGNED_COMMAND_VERBS +
90 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060091 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -060092 UNSIGNED_COMMAND_VERBS +
93 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060094
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070095{
96 face->setInterestFilter("/localhost/nfd/faces",
97 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060098
99 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
100 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700101}
102
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600103FaceManager::~FaceManager()
104{
105
106}
107
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700108void
109FaceManager::setConfigFile(ConfigFile& configFile)
110{
111 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600112 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700113}
114
115
116void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600117FaceManager::onConfig(const ConfigSection& configSection,
118 bool isDryRun,
119 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700120{
121 bool hasSeenUnix = false;
122 bool hasSeenTcp = false;
123 bool hasSeenUdp = false;
124 bool hasSeenEther = false;
125
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600126 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
127
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700128 for (ConfigSection::const_iterator item = configSection.begin();
129 item != configSection.end();
130 ++item)
131 {
132 if (item->first == "unix")
133 {
134 if (hasSeenUnix)
135 throw Error("Duplicate \"unix\" section");
136 hasSeenUnix = true;
137
138 processSectionUnix(item->second, isDryRun);
139 }
140 else if (item->first == "tcp")
141 {
142 if (hasSeenTcp)
143 throw Error("Duplicate \"tcp\" section");
144 hasSeenTcp = true;
145
146 processSectionTcp(item->second, isDryRun);
147 }
148 else if (item->first == "udp")
149 {
150 if (hasSeenUdp)
151 throw Error("Duplicate \"udp\" section");
152 hasSeenUdp = true;
153
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600154 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700155 }
156 else if (item->first == "ether")
157 {
158 if (hasSeenEther)
159 throw Error("Duplicate \"ether\" section");
160 hasSeenEther = true;
161
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600162 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700163 }
164 else
165 {
166 throw Error("Unrecognized option \"" + item->first + "\"");
167 }
168 }
169}
170
171void
172FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
173{
174 // ; the unix section contains settings of UNIX stream faces and channels
175 // unix
176 // {
177 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
178 // path /var/run/nfd.sock ; UNIX stream listener path
179 // }
180
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600181#if defined(HAVE_UNIX_SOCKETS)
182
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700183 bool needToListen = true;
184 std::string path = "/var/run/nfd.sock";
185
186 for (ConfigSection::const_iterator i = configSection.begin();
187 i != configSection.end();
188 ++i)
189 {
190 if (i->first == "path")
191 {
192 path = i->second.get_value<std::string>();
193 }
194 else if (i->first == "listen")
195 {
196 needToListen = parseYesNo(i, i->first, "unix");
197 }
198 else
199 {
200 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
201 }
202 }
203
204 if (!isDryRun)
205 {
206 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
207 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
208
209 if (needToListen)
210 {
211 // Should acceptFailed callback be used somehow?
212 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
213 UnixStreamChannel::ConnectFailedCallback());
214 }
215
216 m_factories.insert(std::make_pair("unix", factory));
217 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600218#else
219 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
220#endif // HAVE_UNIX_SOCKETS
221
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700222}
223
224void
225FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
226{
227 // ; the tcp section contains settings of TCP faces and channels
228 // tcp
229 // {
230 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
231 // port 6363 ; TCP listener port number
232 // }
233
234 std::string port = "6363";
235 bool needToListen = true;
236
237 for (ConfigSection::const_iterator i = configSection.begin();
238 i != configSection.end();
239 ++i)
240 {
241 if (i->first == "port")
242 {
243 port = i->second.get_value<std::string>();
244 }
245 else if (i->first == "listen")
246 {
247 needToListen = parseYesNo(i, i->first, "tcp");
248 }
249 else
250 {
251 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
252 }
253 }
254
255 if (!isDryRun)
256 {
257 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
258
259 using namespace boost::asio::ip;
260
261 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
262 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
263
264 if (needToListen)
265 {
266 // Should acceptFailed callback be used somehow?
267
268 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
269 TcpChannel::ConnectFailedCallback());
270 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
271 TcpChannel::ConnectFailedCallback());
272 }
273
274 m_factories.insert(std::make_pair("tcp", factory));
275 m_factories.insert(std::make_pair("tcp4", factory));
276 m_factories.insert(std::make_pair("tcp6", factory));
277 }
278}
279
280void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600281FaceManager::processSectionUdp(const ConfigSection& configSection,
282 bool isDryRun,
283 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700284{
285 // ; the udp section contains settings of UDP faces and channels
286 // udp
287 // {
288 // port 6363 ; UDP unicast port number
289 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
290 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
291
292 // ; NFD creates one UDP multicast face per NIC
293 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
294 // mcast_port 56363 ; UDP multicast port number
295 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
296 // }
297
298 std::string port = "6363";
299 size_t timeout = 30;
300 size_t keepAliveInterval = 25;
301 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600302 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700303 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600304
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700305
306 for (ConfigSection::const_iterator i = configSection.begin();
307 i != configSection.end();
308 ++i)
309 {
310 if (i->first == "port")
311 {
312 port = i->second.get_value<std::string>();
313 }
314 else if (i->first == "idle_timeout")
315 {
316 try
317 {
318 timeout = i->second.get_value<size_t>();
319 }
320 catch (const std::exception& e)
321 {
322 throw ConfigFile::Error("Invalid value for option \"" +
323 i->first + "\" in \"udp\" section");
324 }
325 }
326 else if (i->first == "keep_alive_interval")
327 {
328 try
329 {
330 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700331
332 /// \todo Make use of keepAliveInterval
333 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700334 }
335 catch (const std::exception& e)
336 {
337 throw ConfigFile::Error("Invalid value for option \"" +
338 i->first + "\" in \"udp\" section");
339 }
340 }
341 else if (i->first == "mcast")
342 {
343 useMcast = parseYesNo(i, i->first, "udp");
344 }
345 else if (i->first == "mcast_port")
346 {
347 mcastPort = i->second.get_value<std::string>();
348 }
349 else if (i->first == "mcast_group")
350 {
351 using namespace boost::asio::ip;
352 mcastGroup = i->second.get_value<std::string>();
353 try
354 {
355 address mcastGroupTest = address::from_string(mcastGroup);
356 if (!mcastGroupTest.is_v4())
357 {
358 throw ConfigFile::Error("Invalid value for option \"" +
359 i->first + "\" in \"udp\" section");
360 }
361 }
362 catch(const std::runtime_error& e)
363 {
364 throw ConfigFile::Error("Invalid value for option \"" +
365 i->first + "\" in \"udp\" section");
366 }
367 }
368 else
369 {
370 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
371 }
372 }
373
374 /// \todo what is keep alive interval used for?
375
376 if (!isDryRun)
377 {
378 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
379
Steve DiBenedettob9906cf2014-03-27 09:18:28 -0600380 shared_ptr<UdpChannel> v4Channel =
381 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
382
383 shared_ptr<UdpChannel> v6Channel =
384 factory->createChannel("::", port, time::seconds(timeout));
385
386 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
387 UdpChannel::ConnectFailedCallback());
388
389 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
390 UdpChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700391
392 m_factories.insert(std::make_pair("udp", factory));
393 m_factories.insert(std::make_pair("udp4", factory));
394 m_factories.insert(std::make_pair("udp6", factory));
395
396 if (useMcast)
397 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600398 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
399 i != nicList.end();
400 ++i)
401 {
402 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
403 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
404 {
405 shared_ptr<MulticastUdpFace> newFace =
406 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
407 mcastGroup, mcastPort);
408
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700409 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600410 }
411 }
412 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700413 }
414}
415
416void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600417FaceManager::processSectionEther(const ConfigSection& configSection,
418 bool isDryRun,
419 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700420{
421 // ; the ether section contains settings of Ethernet faces and channels
422 // ether
423 // {
424 // ; NFD creates one Ethernet multicast face per NIC
425 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
426 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
427 // }
428
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600429#if defined(HAVE_PCAP)
430
431 using ethernet::Address;
432
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700433 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600434 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700435
436 for (ConfigSection::const_iterator i = configSection.begin();
437 i != configSection.end();
438 ++i)
439 {
440 if (i->first == "mcast")
441 {
442 useMcast = parseYesNo(i, i->first, "ether");
443 }
444
445 else if (i->first == "mcast_group")
446 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600447 mcastGroup = Address::fromString(i->second.get_value<std::string>());
448 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700449 {
450 throw ConfigFile::Error("Invalid value for option \"" +
451 i->first + "\" in \"ether\" section");
452 }
453 }
454 else
455 {
456 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
457 }
458 }
459
460 if (!isDryRun)
461 {
462 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
463 m_factories.insert(std::make_pair("ether", factory));
464
465 if (useMcast)
466 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600467 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
468 i != nicList.end();
469 ++i)
470 {
471 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
472 if (nic->isUp() && nic->isMulticastCapable())
473 {
474 try
475 {
476 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100477 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700478
479 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600480 }
481 catch (const EthernetFactory::Error& factoryError)
482 {
483 NFD_LOG_ERROR(factoryError.what() << ", continuing");
484 }
485 catch (const EthernetFace::Error& faceError)
486 {
487 NFD_LOG_ERROR(faceError.what() << ", continuing");
488 }
489 }
490 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700491 }
492 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600493#else
494 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
495#endif // HAVE_PCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700496}
497
498
499void
500FaceManager::onFaceRequest(const Interest& request)
501{
502 const Name& command = request.getName();
503 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600504 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700505
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600506 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
507 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
508 {
509 NFD_LOG_INFO("command result: processing verb: " << verb);
510 (unsignedVerbProcessor->second)(this, boost::cref(request));
511 }
512 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600513 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700514 {
515 NFD_LOG_INFO("command result: unsigned verb: " << command);
516 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700517 }
518 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
519 !COMMAND_PREFIX.isPrefixOf(command))
520 {
521 NFD_LOG_INFO("command result: malformed");
522 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700523 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600524 else
525 {
526 validate(request,
527 bind(&FaceManager::onValidatedFaceRequest, this, _1),
528 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
529 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700530}
531
532void
533FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
534{
535 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600536 const Name::Component& verb = command[COMMAND_PREFIX.size()];
537 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700538
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600539 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
540 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700541 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600542 ControlParameters parameters;
543 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700544 {
545 sendResponse(command, 400, "Malformed command");
546 return;
547 }
548
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700549 NFD_LOG_INFO("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600550 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700551 }
552 else
553 {
554 NFD_LOG_INFO("command result: unsupported verb: " << verb);
555 sendResponse(command, 501, "Unsupported command");
556 }
557
558}
559
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700560void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700561FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
562{
563 m_faceTable.add(newFace);
564
565 NFD_LOG_INFO("Created face " << newFace->getUri() << " ID " << newFace->getId());
566}
567
568void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700569FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600570 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700571 const shared_ptr<Face>& newFace)
572{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700573 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600574 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700575
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600576 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700577}
578
579void
580FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
581{
582 NFD_LOG_INFO("Failed to create face: " << reason);
583 sendResponse(requestName, 400, "Failed to create face");
584}
585
586void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600587FaceManager::createFace(const Interest& request,
588 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700589{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600590 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600591 ndn::nfd::FaceCreateCommand command;
592
593 if (!validateParameters(command, parameters))
594 {
595 sendResponse(requestName, 400, "Malformed command");
596 return;
597 }
598
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700599 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600600 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700601 {
602 sendResponse(requestName, 400, "Malformed command");
603 return;
604 }
605
606 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
607 if (factory == m_factories.end())
608 {
609 sendResponse(requestName, 501, "Unsupported protocol");
610 return;
611 }
612
613 factory->second->createFace(uri,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600614 bind(&FaceManager::onCreated, this, requestName, parameters, _1),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700615 bind(&FaceManager::onConnectFailed, this, requestName, _1));
616}
617
618
619void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600620FaceManager::destroyFace(const Interest& request,
621 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700622{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600623 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600624 ndn::nfd::FaceDestroyCommand command;
625
626 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600627 {
628 sendResponse(requestName, 400, "Malformed command");
629 return;
630 }
631
632 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600633 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700634 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700635 target->close();
636 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600637
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600638 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600639
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700640}
641
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600642void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600643FaceManager::onAddFace(shared_ptr<Face> face)
644{
645 ndn::nfd::FaceEventNotification faceCreated(ndn::nfd::FACE_EVENT_CREATED,
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(faceCreated);
652}
653
654void
655FaceManager::onRemoveFace(shared_ptr<Face> face)
656{
657 ndn::nfd::FaceEventNotification faceDestroyed(ndn::nfd::FACE_EVENT_DESTROYED,
658 face->getId(),
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700659 face->getUri().toString(),
660 (face->isLocal() ? ndn::nfd::FACE_IS_LOCAL : 0) |
661 (face->isOnDemand() ? ndn::nfd::FACE_IS_ON_DEMAND : 0));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600662
663 m_notificationStream.postNotification(faceDestroyed);
664}
665
666
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600667bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600668FaceManager::extractLocalControlParameters(const Interest& request,
669 ControlParameters& parameters,
670 ControlCommand& command,
671 shared_ptr<LocalFace>& outFace,
672 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600673{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600674 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600675 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600676 sendResponse(request.getName(), 400, "Malformed command");
677 return false;
678 }
679
680 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
681
682 if (!static_cast<bool>(face))
683 {
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600684 NFD_LOG_INFO("command result: faceid " << request.getIncomingFaceId() << " not found");
685 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600686 return false;
687 }
688 else if (!face->isLocal())
689 {
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600690 NFD_LOG_INFO("command result: cannot enable local control on non-local faceid " <<
691 face->getId());
692 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600693 return false;
694 }
695
696 outFace = dynamic_pointer_cast<LocalFace>(face);
697 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
698
699 return true;
700}
701
702void
703FaceManager::enableLocalControl(const Interest& request,
704 ControlParameters& parameters)
705{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600706 ndn::nfd::FaceEnableLocalControlCommand command;
707
708
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600709 shared_ptr<LocalFace> face;
710 LocalControlFeature feature;
711
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600712 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600713 {
714 face->setLocalControlHeaderFeature(feature, true);
715 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
716 }
717}
718
719void
720FaceManager::disableLocalControl(const Interest& request,
721 ControlParameters& parameters)
722{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600723 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600724 shared_ptr<LocalFace> face;
725 LocalControlFeature feature;
726
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600727 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600728 {
729 face->setLocalControlHeaderFeature(feature, false);
730 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
731 }
732}
733
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600734void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600735FaceManager::listFaces(const Interest& request)
736{
737 const Name& command = request.getName();
738 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700739
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600740 if (commandNComps < LIST_COMMAND_NCOMPS ||
741 !LIST_COMMAND_PREFIX.isPrefixOf(command))
742 {
743 NFD_LOG_INFO("command result: malformed");
744 sendResponse(command, 400, "Malformed command");
745 return;
746 }
747
748 m_statusPublisher.publish();
749}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700750
751} // namespace nfd