blob: 5b7c08d3fbc811cba9c432b62c96e8d8025a5298 [file] [log] [blame]
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Steve DiBenedettoef04f272014-06-04 14:28:31 -06003 * Copyright (c) 2014, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Steve DiBenedettoef04f272014-06-04 14:28:31 -060024 */
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070025
26#include "face-manager.hpp"
27
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060028#include "core/logger.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070029#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060030#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070031#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070032#include "face/tcp-factory.hpp"
33#include "face/udp-factory.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070034#include "core/config-file.hpp"
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060035
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060036#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060038#endif // HAVE_UNIX_SOCKETS
39
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070040#ifdef HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041#include "face/ethernet-factory.hpp"
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070042#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043
Wentao Shang53df1632014-04-21 12:01:32 -070044#ifdef HAVE_WEBSOCKET
45#include "face/websocket-factory.hpp"
46#endif // HAVE_WEBSOCKET
47
Alexander Afanasyev4a771362014-04-24 21:29:33 -070048#include <ndn-cxx/management/nfd-face-event-notification.hpp>
Davide Pesavento52a18f92014-04-10 00:55:01 +020049
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070050namespace nfd {
51
52NFD_LOG_INIT("FaceManager");
53
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060054const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070055
56const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
57 FaceManager::COMMAND_PREFIX.size() +
58 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060059 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070060
61const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
62 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070063 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070064
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060065const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070066 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060067 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060068 Name::Component("create"),
69 &FaceManager::createFace
70 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070071
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060072 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060073 Name::Component("destroy"),
74 &FaceManager::destroyFace
75 ),
76
77 SignedVerbAndProcessor(
78 Name::Component("enable-local-control"),
79 &FaceManager::enableLocalControl
80 ),
81
82 SignedVerbAndProcessor(
83 Name::Component("disable-local-control"),
84 &FaceManager::disableLocalControl
85 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070086 };
87
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060088const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
89 {
90 UnsignedVerbAndProcessor(
91 Name::Component("list"),
92 &FaceManager::listFaces
93 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060094
95 UnsignedVerbAndProcessor(
96 Name::Component("events"),
97 &FaceManager::ignoreUnsignedVerb
98 ),
Steve DiBenedettoef04f272014-06-04 14:28:31 -060099
100 UnsignedVerbAndProcessor(
101 Name::Component("channels"),
102 &FaceManager::listChannels
103 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600104 };
105
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600106const Name FaceManager::FACES_LIST_DATASET_PREFIX("/localhost/nfd/faces/list");
107const size_t FaceManager::FACES_LIST_DATASET_NCOMPS = FACES_LIST_DATASET_PREFIX.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600108
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600109const Name FaceManager::FACE_EVENTS_PREFIX("/localhost/nfd/faces/events");
110
111const Name FaceManager::CHANNELS_LIST_DATASET_PREFIX("/localhost/nfd/faces/channels");
112const size_t FaceManager::CHANNELS_LIST_DATASET_NCOMPS = CHANNELS_LIST_DATASET_PREFIX.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700113
114FaceManager::FaceManager(FaceTable& faceTable,
Vince Lehman5144f822014-07-23 15:12:56 -0700115 shared_ptr<InternalFace> face,
116 ndn::KeyChain& keyChain)
117 : ManagerBase(face, FACE_MANAGER_PRIVILEGE, keyChain)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700118 , m_faceTable(faceTable)
Vince Lehman5144f822014-07-23 15:12:56 -0700119 , m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
120 , m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
Junxiao Shi15b12e72014-08-09 19:56:24 -0700121 , m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600122 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600123 SIGNED_COMMAND_VERBS +
124 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600125 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600126 UNSIGNED_COMMAND_VERBS +
127 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600128
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700129{
130 face->setInterestFilter("/localhost/nfd/faces",
131 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600132
133 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
134 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700135}
136
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600137FaceManager::~FaceManager()
138{
139
140}
141
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700142void
143FaceManager::setConfigFile(ConfigFile& configFile)
144{
145 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600146 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700147}
148
149
150void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600151FaceManager::onConfig(const ConfigSection& configSection,
152 bool isDryRun,
153 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700154{
155 bool hasSeenUnix = false;
156 bool hasSeenTcp = false;
157 bool hasSeenUdp = false;
158 bool hasSeenEther = false;
Wentao Shang53df1632014-04-21 12:01:32 -0700159 bool hasSeenWebSocket = false;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700160
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600161 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
162
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700163 for (ConfigSection::const_iterator item = configSection.begin();
164 item != configSection.end();
165 ++item)
166 {
167 if (item->first == "unix")
168 {
169 if (hasSeenUnix)
170 throw Error("Duplicate \"unix\" section");
171 hasSeenUnix = true;
172
173 processSectionUnix(item->second, isDryRun);
174 }
175 else if (item->first == "tcp")
176 {
177 if (hasSeenTcp)
178 throw Error("Duplicate \"tcp\" section");
179 hasSeenTcp = true;
180
181 processSectionTcp(item->second, isDryRun);
182 }
183 else if (item->first == "udp")
184 {
185 if (hasSeenUdp)
186 throw Error("Duplicate \"udp\" section");
187 hasSeenUdp = true;
188
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600189 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700190 }
191 else if (item->first == "ether")
192 {
193 if (hasSeenEther)
194 throw Error("Duplicate \"ether\" section");
195 hasSeenEther = true;
196
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600197 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700198 }
Wentao Shang53df1632014-04-21 12:01:32 -0700199 else if (item->first == "websocket")
200 {
201 if (hasSeenWebSocket)
202 throw Error("Duplicate \"websocket\" section");
203 hasSeenWebSocket = true;
204
205 processSectionWebSocket(item->second, isDryRun);
206 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700207 else
208 {
209 throw Error("Unrecognized option \"" + item->first + "\"");
210 }
211 }
212}
213
214void
215FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
216{
217 // ; the unix section contains settings of UNIX stream faces and channels
218 // unix
219 // {
220 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
221 // path /var/run/nfd.sock ; UNIX stream listener path
222 // }
223
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600224#if defined(HAVE_UNIX_SOCKETS)
225
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700226 bool needToListen = true;
227 std::string path = "/var/run/nfd.sock";
228
229 for (ConfigSection::const_iterator i = configSection.begin();
230 i != configSection.end();
231 ++i)
232 {
233 if (i->first == "path")
234 {
235 path = i->second.get_value<std::string>();
236 }
237 else if (i->first == "listen")
238 {
239 needToListen = parseYesNo(i, i->first, "unix");
240 }
241 else
242 {
243 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
244 }
245 }
246
247 if (!isDryRun)
248 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300249 if (m_factories.count("unix") > 0)
250 {
251 return;
252 // shared_ptr<UnixStreamFactory> factory
253 // = static_pointer_cast<UnixStreamFactory>(m_factories["unix"]);
254 // shared_ptr<UnixStreamChannel> unixChannel = factory->findChannel(path);
255
256 // if (static_cast<bool>(unixChannel))
257 // {
258 // return;
259 // }
260 }
261
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700262 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
263 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
264
265 if (needToListen)
266 {
267 // Should acceptFailed callback be used somehow?
268 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
269 UnixStreamChannel::ConnectFailedCallback());
270 }
271
272 m_factories.insert(std::make_pair("unix", factory));
273 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600274#else
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300275 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, "
276 "cannot process \"unix\" section");
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600277#endif // HAVE_UNIX_SOCKETS
278
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700279}
280
281void
282FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
283{
284 // ; the tcp section contains settings of TCP faces and channels
285 // tcp
286 // {
287 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
288 // port 6363 ; TCP listener port number
289 // }
290
291 std::string port = "6363";
292 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600293 bool enableV4 = true;
294 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700295
296 for (ConfigSection::const_iterator i = configSection.begin();
297 i != configSection.end();
298 ++i)
299 {
300 if (i->first == "port")
301 {
302 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600303 try
304 {
305 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
306 NFD_LOG_TRACE("TCP port set to " << portNo);
307 }
308 catch (const std::bad_cast& error)
309 {
310 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600311 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600312 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700313 }
314 else if (i->first == "listen")
315 {
316 needToListen = parseYesNo(i, i->first, "tcp");
317 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600318 else if (i->first == "enable_v4")
319 {
320 enableV4 = parseYesNo(i, i->first, "tcp");
321 }
322 else if (i->first == "enable_v6")
323 {
324 enableV6 = parseYesNo(i, i->first, "tcp");
325 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700326 else
327 {
328 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
329 }
330 }
331
Steve DiBenedetto95152872014-04-11 12:40:59 -0600332 if (!enableV4 && !enableV6)
333 {
334 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
335 " Remove \"tcp\" section to disable TCP channels or"
336 " re-enable at least one channel type.");
337 }
338
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700339 if (!isDryRun)
340 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300341 if (m_factories.count("tcp") > 0)
342 {
343 return;
344 }
345
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700346 shared_ptr<TcpFactory> factory = ndn::make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600347 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700348
Steve DiBenedetto95152872014-04-11 12:40:59 -0600349 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700350 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600351 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
352 if (needToListen)
353 {
354 // Should acceptFailed callback be used somehow?
355 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
356 TcpChannel::ConnectFailedCallback());
357 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700358
Steve DiBenedetto95152872014-04-11 12:40:59 -0600359 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700360 }
361
Steve DiBenedetto95152872014-04-11 12:40:59 -0600362 if (enableV6)
363 {
364 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
365 if (needToListen)
366 {
367 // Should acceptFailed callback be used somehow?
368 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
369 TcpChannel::ConnectFailedCallback());
370 }
371
372 m_factories.insert(std::make_pair("tcp6", factory));
373 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700374 }
375}
376
377void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600378FaceManager::processSectionUdp(const ConfigSection& configSection,
379 bool isDryRun,
380 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700381{
382 // ; the udp section contains settings of UDP faces and channels
383 // udp
384 // {
385 // port 6363 ; UDP unicast port number
386 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
387 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
388
389 // ; NFD creates one UDP multicast face per NIC
390 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
391 // mcast_port 56363 ; UDP multicast port number
392 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
393 // }
394
395 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600396 bool enableV4 = true;
397 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700398 size_t timeout = 30;
399 size_t keepAliveInterval = 25;
400 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600401 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700402 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600403
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700404
405 for (ConfigSection::const_iterator i = configSection.begin();
406 i != configSection.end();
407 ++i)
408 {
409 if (i->first == "port")
410 {
411 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600412 try
413 {
414 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
415 NFD_LOG_TRACE("UDP port set to " << portNo);
416 }
417 catch (const std::bad_cast& error)
418 {
419 throw ConfigFile::Error("Invalid value for option " +
420 i->first + "\" in \"udp\" section");
421 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700422 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600423 else if (i->first == "enable_v4")
424 {
425 enableV4 = parseYesNo(i, i->first, "udp");
426 }
427 else if (i->first == "enable_v6")
428 {
429 enableV6 = parseYesNo(i, i->first, "udp");
430 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700431 else if (i->first == "idle_timeout")
432 {
433 try
434 {
435 timeout = i->second.get_value<size_t>();
436 }
437 catch (const std::exception& e)
438 {
439 throw ConfigFile::Error("Invalid value for option \"" +
440 i->first + "\" in \"udp\" section");
441 }
442 }
443 else if (i->first == "keep_alive_interval")
444 {
445 try
446 {
447 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700448
449 /// \todo Make use of keepAliveInterval
450 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700451 }
452 catch (const std::exception& e)
453 {
454 throw ConfigFile::Error("Invalid value for option \"" +
455 i->first + "\" in \"udp\" section");
456 }
457 }
458 else if (i->first == "mcast")
459 {
460 useMcast = parseYesNo(i, i->first, "udp");
461 }
462 else if (i->first == "mcast_port")
463 {
464 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600465 try
466 {
467 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
468 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
469 }
470 catch (const std::bad_cast& error)
471 {
472 throw ConfigFile::Error("Invalid value for option " +
473 i->first + "\" in \"udp\" section");
474 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700475 }
476 else if (i->first == "mcast_group")
477 {
478 using namespace boost::asio::ip;
479 mcastGroup = i->second.get_value<std::string>();
480 try
481 {
482 address mcastGroupTest = address::from_string(mcastGroup);
483 if (!mcastGroupTest.is_v4())
484 {
485 throw ConfigFile::Error("Invalid value for option \"" +
486 i->first + "\" in \"udp\" section");
487 }
488 }
489 catch(const std::runtime_error& e)
490 {
491 throw ConfigFile::Error("Invalid value for option \"" +
492 i->first + "\" in \"udp\" section");
493 }
494 }
495 else
496 {
497 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
498 }
499 }
500
Steve DiBenedetto95152872014-04-11 12:40:59 -0600501 if (!enableV4 && !enableV6)
502 {
503 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
504 " Remove \"udp\" section to disable UDP channels or"
505 " re-enable at least one channel type.");
506 }
507 else if (useMcast && !enableV4)
508 {
509 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
510 " have been disabled (conflicting configuration options set)");
511 }
512
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700513 /// \todo what is keep alive interval used for?
514
515 if (!isDryRun)
516 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300517 shared_ptr<UdpFactory> factory;
518 bool isReload = false;
519 if (m_factories.count("udp") > 0) {
520 isReload = true;
521 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
522 }
523 else {
524 factory = ndn::make_shared<UdpFactory>(port);
525 m_factories.insert(std::make_pair("udp", factory));
526 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700527
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300528 if (!isReload && enableV4)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600529 {
530 shared_ptr<UdpChannel> v4Channel =
531 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
532
533 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
534 UdpChannel::ConnectFailedCallback());
535
536 m_factories.insert(std::make_pair("udp4", factory));
537 }
538
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300539 if (!isReload && enableV6)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600540 {
541 shared_ptr<UdpChannel> v6Channel =
542 factory->createChannel("::", port, time::seconds(timeout));
543
544 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
545 UdpChannel::ConnectFailedCallback());
546 m_factories.insert(std::make_pair("udp6", factory));
547 }
548
549 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700550 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200551 std::list<shared_ptr<NetworkInterfaceInfo> > ipv4MulticastInterfaces;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600552 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
553 i != nicList.end();
554 ++i)
555 {
556 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
557 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
558 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200559 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600560 }
561 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200562
563 bool isNicNameNecessary = false;
564
565#if defined(__linux__)
566 if (ipv4MulticastInterfaces.size() > 1)
567 {
568 //On Linux, if we have more than one MulticastUdpFace we need to specify
569 //the name of the interface
570 isNicNameNecessary = true;
571 }
572#endif
573
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300574 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
575 for (UdpFactory::MulticastFaceMap::const_iterator i =
576 factory->getMulticastFaces().begin();
577 i != factory->getMulticastFaces().end();
578 ++i)
579 {
580 multicastFacesToRemove.push_back(i->second);
581 }
582
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200583 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i =
584 ipv4MulticastInterfaces.begin();
585 i != ipv4MulticastInterfaces.end();
586 ++i)
587 {
588 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
589 shared_ptr<MulticastUdpFace> newFace;
590 newFace = factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
591 mcastGroup,
592 mcastPort,
593 isNicNameNecessary ? nic->name : "");
594
595 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300596 multicastFacesToRemove.remove(newFace);
597 }
598
599 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
600 multicastFacesToRemove.begin();
601 i != multicastFacesToRemove.end();
602 ++i)
603 {
604 (*i)->close();
605 }
606 }
607 else
608 {
609 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
610 for (UdpFactory::MulticastFaceMap::const_iterator i =
611 factory->getMulticastFaces().begin();
612 i != factory->getMulticastFaces().end();
613 ++i)
614 {
615 multicastFacesToRemove.push_back(i->second);
616 }
617
618 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
619 multicastFacesToRemove.begin();
620 i != multicastFacesToRemove.end();
621 ++i)
622 {
623 (*i)->close();
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200624 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600625 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700626 }
627}
628
629void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600630FaceManager::processSectionEther(const ConfigSection& configSection,
631 bool isDryRun,
632 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700633{
634 // ; the ether section contains settings of Ethernet faces and channels
635 // ether
636 // {
637 // ; NFD creates one Ethernet multicast face per NIC
638 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
639 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
640 // }
641
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700642#if defined(HAVE_LIBPCAP)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600643
644 using ethernet::Address;
645
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700646 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600647 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700648
649 for (ConfigSection::const_iterator i = configSection.begin();
650 i != configSection.end();
651 ++i)
652 {
653 if (i->first == "mcast")
654 {
655 useMcast = parseYesNo(i, i->first, "ether");
656 }
657
658 else if (i->first == "mcast_group")
659 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600660 mcastGroup = Address::fromString(i->second.get_value<std::string>());
661 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700662 {
663 throw ConfigFile::Error("Invalid value for option \"" +
664 i->first + "\" in \"ether\" section");
665 }
666 }
667 else
668 {
669 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
670 }
671 }
672
673 if (!isDryRun)
674 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300675 shared_ptr<EthernetFactory> factory;
676 if (m_factories.count("ether") > 0) {
677 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
678 }
679 else {
680 factory = ndn::make_shared<EthernetFactory>();
681 m_factories.insert(std::make_pair("ether", factory));
682 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700683
684 if (useMcast)
685 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300686 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
687 for (EthernetFactory::MulticastFaceMap::const_iterator i =
688 factory->getMulticastFaces().begin();
689 i != factory->getMulticastFaces().end();
690 ++i)
691 {
692 multicastFacesToRemove.push_back(i->second);
693 }
694
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600695 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
696 i != nicList.end();
697 ++i)
698 {
699 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
700 if (nic->isUp() && nic->isMulticastCapable())
701 {
702 try
703 {
704 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100705 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700706
707 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300708 multicastFacesToRemove.remove(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600709 }
710 catch (const EthernetFactory::Error& factoryError)
711 {
712 NFD_LOG_ERROR(factoryError.what() << ", continuing");
713 }
714 catch (const EthernetFace::Error& faceError)
715 {
716 NFD_LOG_ERROR(faceError.what() << ", continuing");
717 }
718 }
719 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300720
721 for (std::list<shared_ptr<EthernetFace> >::iterator i =
722 multicastFacesToRemove.begin();
723 i != multicastFacesToRemove.end();
724 ++i)
725 {
726 (*i)->close();
727 }
728 }
729 else
730 {
731 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
732 for (EthernetFactory::MulticastFaceMap::const_iterator i =
733 factory->getMulticastFaces().begin();
734 i != factory->getMulticastFaces().end();
735 ++i)
736 {
737 multicastFacesToRemove.push_back(i->second);
738 }
739
740 for (std::list<shared_ptr<EthernetFace> >::iterator i =
741 multicastFacesToRemove.begin();
742 i != multicastFacesToRemove.end();
743 ++i)
744 {
745 (*i)->close();
746 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700747 }
748 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600749#else
750 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700751#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700752}
753
Wentao Shang53df1632014-04-21 12:01:32 -0700754void
755FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
756{
757 // ; the websocket section contains settings of WebSocket faces and channels
758 // websocket
759 // {
760 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
761 // port 9696 ; WebSocket listener port number
762 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
763 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
764 // }
765
766#if defined(HAVE_WEBSOCKET)
767
768 std::string port = "9696";
769 bool needToListen = true;
770 bool enableV4 = true;
771 bool enableV6 = true;
772
773 for (ConfigSection::const_iterator i = configSection.begin();
774 i != configSection.end();
775 ++i)
776 {
777 if (i->first == "port")
778 {
779 port = i->second.get_value<std::string>();
780 try
781 {
782 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
783 NFD_LOG_TRACE("WebSocket port set to " << portNo);
784 }
785 catch (const std::bad_cast& error)
786 {
787 throw ConfigFile::Error("Invalid value for option " +
788 i->first + "\" in \"websocket\" section");
789 }
790 }
791 else if (i->first == "listen")
792 {
793 needToListen = parseYesNo(i, i->first, "websocket");
794 }
795 else if (i->first == "enable_v4")
796 {
797 enableV4 = parseYesNo(i, i->first, "websocket");
798 }
799 else if (i->first == "enable_v6")
800 {
801 enableV6 = parseYesNo(i, i->first, "websocket");
802 }
803 else
804 {
805 throw ConfigFile::Error("Unrecognized option \"" +
806 i->first + "\" in \"websocket\" section");
807 }
808 }
809
810 if (!enableV4 && !enableV6)
811 {
812 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
813 " Remove \"websocket\" section to disable WebSocket channels or"
814 " re-enable at least one channel type.");
815 }
816
817 if (!enableV4 && enableV6)
818 {
819 throw ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel.");
820 }
821
822 if (!isDryRun)
823 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300824 if (m_factories.count("websocket") > 0)
825 {
826 return;
827 }
828
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700829 shared_ptr<WebSocketFactory> factory = ndn::make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700830 m_factories.insert(std::make_pair("websocket", factory));
Wentao Shang53df1632014-04-21 12:01:32 -0700831
832 if (enableV6 && enableV4)
833 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600834 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700835 if (needToListen)
836 {
837 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
838 }
839
840 m_factories.insert(std::make_pair("websocket46", factory));
841 }
842 else if (enableV4)
843 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600844 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700845 if (needToListen)
846 {
847 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
848 }
849
850 m_factories.insert(std::make_pair("websocket4", factory));
851 }
852 }
853#else
854 throw ConfigFile::Error("NFD was compiled without WebSocket, "
855 "cannot process \"websocket\" section");
856#endif // HAVE_WEBSOCKET
857}
858
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700859
860void
861FaceManager::onFaceRequest(const Interest& request)
862{
863 const Name& command = request.getName();
864 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600865 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700866
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300867 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor =
868 m_unsignedVerbDispatch.find(verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600869 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
870 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700871 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700872 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600873 }
874 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600875 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700876 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700877 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700878 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700879 }
880 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
881 !COMMAND_PREFIX.isPrefixOf(command))
882 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700883 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700884 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700885 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600886 else
887 {
888 validate(request,
889 bind(&FaceManager::onValidatedFaceRequest, this, _1),
890 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
891 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700892}
893
894void
895FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
896{
897 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600898 const Name::Component& verb = command[COMMAND_PREFIX.size()];
899 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700900
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600901 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
902 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700903 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600904 ControlParameters parameters;
905 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700906 {
907 sendResponse(command, 400, "Malformed command");
908 return;
909 }
910
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700911 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600912 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700913 }
914 else
915 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700916 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700917 sendResponse(command, 501, "Unsupported command");
918 }
919
920}
921
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700922void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700923FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
924{
925 m_faceTable.add(newFace);
926
Junxiao Shi6e694322014-04-03 10:27:13 -0700927 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700928}
929
930void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700931FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600932 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700933 const shared_ptr<Face>& newFace)
934{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700935 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600936 parameters.setFaceId(newFace->getId());
Steve DiBenedetto25999282014-05-22 15:25:12 -0600937 parameters.setUri(newFace->getRemoteUri().toString());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700938
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600939 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700940}
941
942void
943FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
944{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700945 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600946 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700947}
948
949void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600950FaceManager::createFace(const Interest& request,
951 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700952{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600953 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600954 ndn::nfd::FaceCreateCommand command;
955
956 if (!validateParameters(command, parameters))
957 {
958 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600959 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600960 return;
961 }
962
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700963 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600964 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700965 {
966 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600967 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700968 return;
969 }
970
971 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
972 if (factory == m_factories.end())
973 {
974 sendResponse(requestName, 501, "Unsupported protocol");
975 return;
976 }
977
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600978 try
979 {
980 factory->second->createFace(uri,
981 bind(&FaceManager::onCreated,
982 this, requestName, parameters, _1),
983 bind(&FaceManager::onConnectFailed,
984 this, requestName, _1));
985 }
986 catch (const std::runtime_error& error)
987 {
988 std::string errorMessage = "NFD error: ";
989 errorMessage += error.what();
990
991 NFD_LOG_ERROR(errorMessage);
992 sendResponse(requestName, 500, errorMessage);
993 }
994 catch (const std::logic_error& error)
995 {
996 std::string errorMessage = "NFD error: ";
997 errorMessage += error.what();
998
999 NFD_LOG_ERROR(errorMessage);
1000 sendResponse(requestName, 500, errorMessage);
1001 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001002}
1003
1004
1005void
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001006FaceManager::destroyFace(const Interest& request,
1007 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001008{
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001009 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001010 ndn::nfd::FaceDestroyCommand command;
1011
1012 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001013 {
1014 sendResponse(requestName, 400, "Malformed command");
1015 return;
1016 }
1017
1018 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001019 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001020 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001021 target->close();
1022 }
Steve DiBenedettoba749052014-03-22 19:54:53 -06001023
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001024 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001025
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001026}
1027
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001028void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001029FaceManager::onAddFace(shared_ptr<Face> face)
1030{
Junxiao Shi6e694322014-04-03 10:27:13 -07001031 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001032 notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
1033 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001034
Junxiao Shi6e694322014-04-03 10:27:13 -07001035 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001036}
1037
1038void
1039FaceManager::onRemoveFace(shared_ptr<Face> face)
1040{
Junxiao Shi6e694322014-04-03 10:27:13 -07001041 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001042 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
1043 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001044
Junxiao Shi6e694322014-04-03 10:27:13 -07001045 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001046}
1047
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001048bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001049FaceManager::extractLocalControlParameters(const Interest& request,
1050 ControlParameters& parameters,
1051 ControlCommand& command,
1052 shared_ptr<LocalFace>& outFace,
1053 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001054{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001055 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001056 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001057 sendResponse(request.getName(), 400, "Malformed command");
1058 return false;
1059 }
1060
1061 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
1062
1063 if (!static_cast<bool>(face))
1064 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001065 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001066 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001067 return false;
1068 }
1069 else if (!face->isLocal())
1070 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001071 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
1072 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001073 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001074 return false;
1075 }
1076
1077 outFace = dynamic_pointer_cast<LocalFace>(face);
1078 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
1079
1080 return true;
1081}
1082
1083void
1084FaceManager::enableLocalControl(const Interest& request,
1085 ControlParameters& parameters)
1086{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001087 ndn::nfd::FaceEnableLocalControlCommand command;
1088
1089
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001090 shared_ptr<LocalFace> face;
1091 LocalControlFeature feature;
1092
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001093 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001094 {
1095 face->setLocalControlHeaderFeature(feature, true);
1096 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1097 }
1098}
1099
1100void
1101FaceManager::disableLocalControl(const Interest& request,
1102 ControlParameters& parameters)
1103{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001104 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001105 shared_ptr<LocalFace> face;
1106 LocalControlFeature feature;
1107
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001108 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001109 {
1110 face->setLocalControlHeaderFeature(feature, false);
1111 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1112 }
1113}
1114
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001115void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001116FaceManager::listFaces(const Interest& request)
1117{
1118 const Name& command = request.getName();
1119 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001120
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001121 if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
1122 !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001123 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001124 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001125 sendResponse(command, 400, "Malformed command");
1126 return;
1127 }
1128
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001129 m_faceStatusPublisher.publish();
1130}
1131
1132void
1133FaceManager::listChannels(const Interest& request)
1134{
1135 NFD_LOG_DEBUG("in listChannels");
1136 const Name& command = request.getName();
1137 const size_t commandNComps = command.size();
1138
1139 if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
1140 !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
1141 {
1142 NFD_LOG_DEBUG("command result: malformed");
1143 sendResponse(command, 400, "Malformed command");
1144 return;
1145 }
1146
1147 NFD_LOG_DEBUG("publishing");
1148 m_channelStatusPublisher.publish();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001149}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001150
Alexander Afanasyev5959b012014-06-02 19:18:12 +03001151shared_ptr<ProtocolFactory>
1152FaceManager::findFactory(const std::string& protocol)
1153{
1154 FactoryMap::iterator factory = m_factories.find(protocol);
1155 if (factory != m_factories.end())
1156 return factory->second;
1157 else
1158 return shared_ptr<ProtocolFactory>();
1159}
1160
1161
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001162} // namespace nfd