blob: 692acf9649b045c8c07949bcb7a82b36c547b931 [file] [log] [blame]
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08003 * Copyright (c) 2014-2015, 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 DiBenedetto4aca99c2014-03-11 11:27:54 -060029#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070030#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070031#include "face/tcp-factory.hpp"
32#include "face/udp-factory.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070033#include "core/config-file.hpp"
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060034
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060035#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070036#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060037#endif // HAVE_UNIX_SOCKETS
38
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070039#ifdef HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070040#include "face/ethernet-factory.hpp"
Alexander Afanasyeveae4f802015-01-05 17:28:15 -080041#include "face/ethernet-face.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>
Chengyu Fan320d2332014-10-29 16:40:33 -060049#include <ndn-cxx/management/nfd-face-query-filter.hpp>
Davide Pesavento52a18f92014-04-10 00:55:01 +020050
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070051namespace nfd {
52
53NFD_LOG_INIT("FaceManager");
54
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060055const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070056
57const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
58 FaceManager::COMMAND_PREFIX.size() +
59 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060060 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070061
62const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
63 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070064 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070065
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060066const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070067 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060068 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060069 Name::Component("create"),
70 &FaceManager::createFace
71 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070072
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060073 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060074 Name::Component("destroy"),
75 &FaceManager::destroyFace
76 ),
77
78 SignedVerbAndProcessor(
79 Name::Component("enable-local-control"),
80 &FaceManager::enableLocalControl
81 ),
82
83 SignedVerbAndProcessor(
84 Name::Component("disable-local-control"),
85 &FaceManager::disableLocalControl
86 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070087 };
88
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060089const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
90 {
91 UnsignedVerbAndProcessor(
92 Name::Component("list"),
93 &FaceManager::listFaces
94 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060095
96 UnsignedVerbAndProcessor(
97 Name::Component("events"),
98 &FaceManager::ignoreUnsignedVerb
99 ),
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600100
101 UnsignedVerbAndProcessor(
102 Name::Component("channels"),
103 &FaceManager::listChannels
104 ),
Chengyu Fan320d2332014-10-29 16:40:33 -0600105
106 UnsignedVerbAndProcessor(
107 Name::Component("query"),
108 &FaceManager::listQueriedFaces
109 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600110 };
111
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600112const Name FaceManager::FACES_LIST_DATASET_PREFIX("/localhost/nfd/faces/list");
113const size_t FaceManager::FACES_LIST_DATASET_NCOMPS = FACES_LIST_DATASET_PREFIX.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600114
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600115const Name FaceManager::FACE_EVENTS_PREFIX("/localhost/nfd/faces/events");
116
117const Name FaceManager::CHANNELS_LIST_DATASET_PREFIX("/localhost/nfd/faces/channels");
118const size_t FaceManager::CHANNELS_LIST_DATASET_NCOMPS = CHANNELS_LIST_DATASET_PREFIX.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700119
Chengyu Fan320d2332014-10-29 16:40:33 -0600120const Name FaceManager::FACES_QUERY_DATASET_PREFIX("/localhost/nfd/faces/query");
121const size_t FaceManager::FACES_QUERY_DATASET_NCOMPS = FACES_QUERY_DATASET_PREFIX.size() + 1;
122
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700123FaceManager::FaceManager(FaceTable& faceTable,
Vince Lehman5144f822014-07-23 15:12:56 -0700124 shared_ptr<InternalFace> face,
125 ndn::KeyChain& keyChain)
126 : ManagerBase(face, FACE_MANAGER_PRIVILEGE, keyChain)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700127 , m_faceTable(faceTable)
Junxiao Shi1e064172014-12-14 19:37:46 -0700128 , m_faceAddConn(m_faceTable.onAdd.connect(bind(&FaceManager::onAddFace, this, _1)))
129 , m_faceRemoveConn(m_faceTable.onRemove.connect(bind(&FaceManager::onRemoveFace, this, _1)))
Vince Lehman5144f822014-07-23 15:12:56 -0700130 , m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
131 , m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
Junxiao Shi15b12e72014-08-09 19:56:24 -0700132 , m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600133 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600134 SIGNED_COMMAND_VERBS +
135 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600136 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600137 UNSIGNED_COMMAND_VERBS +
138 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600139
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700140{
141 face->setInterestFilter("/localhost/nfd/faces",
142 bind(&FaceManager::onFaceRequest, this, _2));
143}
144
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600145FaceManager::~FaceManager()
146{
147
148}
149
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700150void
151FaceManager::setConfigFile(ConfigFile& configFile)
152{
153 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600154 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700155}
156
157
158void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600159FaceManager::onConfig(const ConfigSection& configSection,
160 bool isDryRun,
161 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700162{
163 bool hasSeenUnix = false;
164 bool hasSeenTcp = false;
165 bool hasSeenUdp = false;
166 bool hasSeenEther = false;
Wentao Shang53df1632014-04-21 12:01:32 -0700167 bool hasSeenWebSocket = false;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700168
Davide Pesaventob499a602014-11-18 22:36:56 +0100169 const std::vector<NetworkInterfaceInfo> nicList(listNetworkInterfaces());
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600170
Davide Pesaventob499a602014-11-18 22:36:56 +0100171 for (const auto& item : configSection)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700172 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100173 if (item.first == "unix")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700174 {
175 if (hasSeenUnix)
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700176 BOOST_THROW_EXCEPTION(Error("Duplicate \"unix\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700177 hasSeenUnix = true;
178
Davide Pesaventob499a602014-11-18 22:36:56 +0100179 processSectionUnix(item.second, isDryRun);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700180 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100181 else if (item.first == "tcp")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700182 {
183 if (hasSeenTcp)
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700184 BOOST_THROW_EXCEPTION(Error("Duplicate \"tcp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700185 hasSeenTcp = true;
186
Davide Pesaventob499a602014-11-18 22:36:56 +0100187 processSectionTcp(item.second, isDryRun);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700188 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100189 else if (item.first == "udp")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700190 {
191 if (hasSeenUdp)
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700192 BOOST_THROW_EXCEPTION(Error("Duplicate \"udp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700193 hasSeenUdp = true;
194
Davide Pesaventob499a602014-11-18 22:36:56 +0100195 processSectionUdp(item.second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700196 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100197 else if (item.first == "ether")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700198 {
199 if (hasSeenEther)
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700200 BOOST_THROW_EXCEPTION(Error("Duplicate \"ether\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700201 hasSeenEther = true;
202
Davide Pesaventob499a602014-11-18 22:36:56 +0100203 processSectionEther(item.second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700204 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100205 else if (item.first == "websocket")
Wentao Shang53df1632014-04-21 12:01:32 -0700206 {
207 if (hasSeenWebSocket)
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700208 BOOST_THROW_EXCEPTION(Error("Duplicate \"websocket\" section"));
Wentao Shang53df1632014-04-21 12:01:32 -0700209 hasSeenWebSocket = true;
210
Davide Pesaventob499a602014-11-18 22:36:56 +0100211 processSectionWebSocket(item.second, isDryRun);
Wentao Shang53df1632014-04-21 12:01:32 -0700212 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700213 else
214 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700215 BOOST_THROW_EXCEPTION(Error("Unrecognized option \"" + item.first + "\""));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700216 }
217 }
218}
219
220void
221FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
222{
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700223 // ; the unix section contains settings of Unix stream faces and channels
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700224 // unix
225 // {
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700226 // path /var/run/nfd.sock ; Unix stream listener path
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700227 // }
228
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600229#if defined(HAVE_UNIX_SOCKETS)
230
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700231 std::string path = "/var/run/nfd.sock";
232
233 for (ConfigSection::const_iterator i = configSection.begin();
234 i != configSection.end();
235 ++i)
236 {
237 if (i->first == "path")
238 {
239 path = i->second.get_value<std::string>();
240 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700241 else
242 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700243 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first + "\" in "
244 "\"unix\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700245 }
246 }
247
248 if (!isDryRun)
249 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300250 if (m_factories.count("unix") > 0)
251 {
252 return;
253 // shared_ptr<UnixStreamFactory> factory
254 // = static_pointer_cast<UnixStreamFactory>(m_factories["unix"]);
255 // shared_ptr<UnixStreamChannel> unixChannel = factory->findChannel(path);
256
257 // if (static_cast<bool>(unixChannel))
258 // {
259 // return;
260 // }
261 }
262
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700263 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
264 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
265
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700266 // Should acceptFailed callback be used somehow?
267 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
268 UnixStreamChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700269
270 m_factories.insert(std::make_pair("unix", factory));
271 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600272#else
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700273 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without Unix sockets support, "
274 "cannot process \"unix\" section"));
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600275#endif // HAVE_UNIX_SOCKETS
276
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700277}
278
279void
280FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
281{
282 // ; the tcp section contains settings of TCP faces and channels
283 // tcp
284 // {
285 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
286 // port 6363 ; TCP listener port number
287 // }
288
289 std::string port = "6363";
290 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600291 bool enableV4 = true;
292 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700293
294 for (ConfigSection::const_iterator i = configSection.begin();
295 i != configSection.end();
296 ++i)
297 {
298 if (i->first == "port")
299 {
300 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600301 try
302 {
303 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
304 NFD_LOG_TRACE("TCP port set to " << portNo);
305 }
306 catch (const std::bad_cast& error)
307 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700308 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
309 i->first + "\" in \"tcp\" section"));
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600310 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700311 }
312 else if (i->first == "listen")
313 {
314 needToListen = parseYesNo(i, i->first, "tcp");
315 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600316 else if (i->first == "enable_v4")
317 {
318 enableV4 = parseYesNo(i, i->first, "tcp");
319 }
320 else if (i->first == "enable_v6")
321 {
322 enableV6 = parseYesNo(i, i->first, "tcp");
323 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700324 else
325 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700326 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first + "\" in "
327 "\"tcp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700328 }
329 }
330
Steve DiBenedetto95152872014-04-11 12:40:59 -0600331 if (!enableV4 && !enableV6)
332 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700333 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
334 " Remove \"tcp\" section to disable TCP channels or"
335 " re-enable at least one channel type."));
Steve DiBenedetto95152872014-04-11 12:40:59 -0600336 }
337
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700338 if (!isDryRun)
339 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300340 if (m_factories.count("tcp") > 0)
341 {
342 return;
343 }
344
Davide Pesaventob499a602014-11-18 22:36:56 +0100345 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600346 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700347
Steve DiBenedetto95152872014-04-11 12:40:59 -0600348 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700349 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600350 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
351 if (needToListen)
352 {
353 // Should acceptFailed callback be used somehow?
354 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
355 TcpChannel::ConnectFailedCallback());
356 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700357
Steve DiBenedetto95152872014-04-11 12:40:59 -0600358 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700359 }
360
Steve DiBenedetto95152872014-04-11 12:40:59 -0600361 if (enableV6)
362 {
363 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
364 if (needToListen)
365 {
366 // Should acceptFailed callback be used somehow?
367 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
368 TcpChannel::ConnectFailedCallback());
369 }
370
371 m_factories.insert(std::make_pair("tcp6", factory));
372 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700373 }
374}
375
376void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600377FaceManager::processSectionUdp(const ConfigSection& configSection,
378 bool isDryRun,
Davide Pesaventob499a602014-11-18 22:36:56 +0100379 const std::vector<NetworkInterfaceInfo>& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700380{
381 // ; the udp section contains settings of UDP faces and channels
382 // udp
383 // {
384 // port 6363 ; UDP unicast port number
Chengyu Fanaddecff2015-02-10 14:09:01 -0700385 // idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
386 // keep_alive_interval 25 ; interval (seconds) between keep-alive refreshes
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700387
388 // ; NFD creates one UDP multicast face per NIC
389 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
390 // mcast_port 56363 ; UDP multicast port number
391 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
392 // }
393
394 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600395 bool enableV4 = true;
396 bool enableV6 = true;
Chengyu Fanaddecff2015-02-10 14:09:01 -0700397 size_t timeout = 600;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700398 size_t keepAliveInterval = 25;
399 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600400 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700401 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600402
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700403
404 for (ConfigSection::const_iterator i = configSection.begin();
405 i != configSection.end();
406 ++i)
407 {
408 if (i->first == "port")
409 {
410 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600411 try
412 {
413 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
414 NFD_LOG_TRACE("UDP port set to " << portNo);
415 }
416 catch (const std::bad_cast& error)
417 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700418 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
419 i->first + "\" in \"udp\" section"));
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600420 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700421 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600422 else if (i->first == "enable_v4")
423 {
424 enableV4 = parseYesNo(i, i->first, "udp");
425 }
426 else if (i->first == "enable_v6")
427 {
428 enableV6 = parseYesNo(i, i->first, "udp");
429 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700430 else if (i->first == "idle_timeout")
431 {
432 try
433 {
434 timeout = i->second.get_value<size_t>();
435 }
436 catch (const std::exception& e)
437 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700438 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
439 i->first + "\" in \"udp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700440 }
441 }
442 else if (i->first == "keep_alive_interval")
443 {
444 try
445 {
446 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700447
448 /// \todo Make use of keepAliveInterval
449 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700450 }
451 catch (const std::exception& e)
452 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700453 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
454 i->first + "\" in \"udp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700455 }
456 }
457 else if (i->first == "mcast")
458 {
459 useMcast = parseYesNo(i, i->first, "udp");
460 }
461 else if (i->first == "mcast_port")
462 {
463 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600464 try
465 {
466 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
467 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
468 }
469 catch (const std::bad_cast& error)
470 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700471 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
472 i->first + "\" in \"udp\" section"));
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600473 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700474 }
475 else if (i->first == "mcast_group")
476 {
477 using namespace boost::asio::ip;
478 mcastGroup = i->second.get_value<std::string>();
479 try
480 {
481 address mcastGroupTest = address::from_string(mcastGroup);
482 if (!mcastGroupTest.is_v4())
483 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700484 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
485 i->first + "\" in \"udp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700486 }
487 }
488 catch(const std::runtime_error& e)
489 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700490 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
491 i->first + "\" in \"udp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700492 }
493 }
494 else
495 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700496 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first + "\" in "
497 "\"udp\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700498 }
499 }
500
Steve DiBenedetto95152872014-04-11 12:40:59 -0600501 if (!enableV4 && !enableV6)
502 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700503 BOOST_THROW_EXCEPTION(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."));
Steve DiBenedetto95152872014-04-11 12:40:59 -0600506 }
507 else if (useMcast && !enableV4)
508 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700509 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
510 " have been disabled (conflicting configuration"
511 " options set)"));
Steve DiBenedetto95152872014-04-11 12:40:59 -0600512 }
513
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700514 /// \todo what is keep alive interval used for?
515
516 if (!isDryRun)
517 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300518 shared_ptr<UdpFactory> factory;
519 bool isReload = false;
520 if (m_factories.count("udp") > 0) {
521 isReload = true;
522 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
523 }
524 else {
Davide Pesaventob499a602014-11-18 22:36:56 +0100525 factory = make_shared<UdpFactory>(port);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300526 m_factories.insert(std::make_pair("udp", factory));
527 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700528
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300529 if (!isReload && enableV4)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600530 {
531 shared_ptr<UdpChannel> v4Channel =
532 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
533
534 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
535 UdpChannel::ConnectFailedCallback());
536
537 m_factories.insert(std::make_pair("udp4", factory));
538 }
539
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300540 if (!isReload && enableV6)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600541 {
542 shared_ptr<UdpChannel> v6Channel =
543 factory->createChannel("::", port, time::seconds(timeout));
544
545 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
546 UdpChannel::ConnectFailedCallback());
547 m_factories.insert(std::make_pair("udp6", factory));
548 }
549
550 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700551 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100552 std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
553 for (const auto& nic : nicList)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600554 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100555 if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty())
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600556 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200557 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600558 }
559 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200560
561 bool isNicNameNecessary = false;
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200562#if defined(__linux__)
563 if (ipv4MulticastInterfaces.size() > 1)
564 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100565 // On Linux if we have more than one MulticastUdpFace
566 // we need to specify the name of the interface
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200567 isNicNameNecessary = true;
568 }
569#endif
570
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300571 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
572 for (UdpFactory::MulticastFaceMap::const_iterator i =
573 factory->getMulticastFaces().begin();
574 i != factory->getMulticastFaces().end();
575 ++i)
576 {
577 multicastFacesToRemove.push_back(i->second);
578 }
579
Davide Pesaventob499a602014-11-18 22:36:56 +0100580 for (const auto& nic : ipv4MulticastInterfaces)
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200581 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200582 shared_ptr<MulticastUdpFace> newFace;
Davide Pesaventob499a602014-11-18 22:36:56 +0100583 newFace = factory->createMulticastFace(nic.ipv4Addresses[0].to_string(),
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200584 mcastGroup,
585 mcastPort,
Davide Pesaventob499a602014-11-18 22:36:56 +0100586 isNicNameNecessary ? nic.name : "");
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200587 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300588 multicastFacesToRemove.remove(newFace);
589 }
590
591 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
592 multicastFacesToRemove.begin();
593 i != multicastFacesToRemove.end();
594 ++i)
595 {
596 (*i)->close();
597 }
598 }
599 else
600 {
601 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
602 for (UdpFactory::MulticastFaceMap::const_iterator i =
603 factory->getMulticastFaces().begin();
604 i != factory->getMulticastFaces().end();
605 ++i)
606 {
607 multicastFacesToRemove.push_back(i->second);
608 }
609
610 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
611 multicastFacesToRemove.begin();
612 i != multicastFacesToRemove.end();
613 ++i)
614 {
615 (*i)->close();
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200616 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600617 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700618 }
619}
620
621void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600622FaceManager::processSectionEther(const ConfigSection& configSection,
623 bool isDryRun,
Davide Pesaventob499a602014-11-18 22:36:56 +0100624 const std::vector<NetworkInterfaceInfo>& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700625{
626 // ; the ether section contains settings of Ethernet faces and channels
627 // ether
628 // {
629 // ; NFD creates one Ethernet multicast face per NIC
630 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
631 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
632 // }
633
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700634#if defined(HAVE_LIBPCAP)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700635 bool useMcast = true;
Davide Pesaventob499a602014-11-18 22:36:56 +0100636 ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700637
638 for (ConfigSection::const_iterator i = configSection.begin();
639 i != configSection.end();
640 ++i)
641 {
642 if (i->first == "mcast")
643 {
644 useMcast = parseYesNo(i, i->first, "ether");
645 }
646
647 else if (i->first == "mcast_group")
648 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100649 mcastGroup = ethernet::Address::fromString(i->second.get_value<std::string>());
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600650 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700651 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700652 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
653 i->first + "\" in \"ether\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700654 }
655 }
656 else
657 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700658 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first +
659 "\" in \"ether\" section"));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700660 }
661 }
662
663 if (!isDryRun)
664 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300665 shared_ptr<EthernetFactory> factory;
666 if (m_factories.count("ether") > 0) {
667 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
668 }
669 else {
Davide Pesaventob499a602014-11-18 22:36:56 +0100670 factory = make_shared<EthernetFactory>();
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300671 m_factories.insert(std::make_pair("ether", factory));
672 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700673
674 if (useMcast)
675 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300676 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
677 for (EthernetFactory::MulticastFaceMap::const_iterator i =
678 factory->getMulticastFaces().begin();
679 i != factory->getMulticastFaces().end();
680 ++i)
681 {
682 multicastFacesToRemove.push_back(i->second);
683 }
684
Davide Pesaventob499a602014-11-18 22:36:56 +0100685 for (const auto& nic : nicList)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600686 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100687 if (nic.isUp() && nic.isMulticastCapable())
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600688 {
689 try
690 {
691 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100692 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700693
694 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300695 multicastFacesToRemove.remove(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600696 }
697 catch (const EthernetFactory::Error& factoryError)
698 {
699 NFD_LOG_ERROR(factoryError.what() << ", continuing");
700 }
701 catch (const EthernetFace::Error& faceError)
702 {
703 NFD_LOG_ERROR(faceError.what() << ", continuing");
704 }
705 }
706 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300707
708 for (std::list<shared_ptr<EthernetFace> >::iterator i =
709 multicastFacesToRemove.begin();
710 i != multicastFacesToRemove.end();
711 ++i)
712 {
713 (*i)->close();
714 }
715 }
716 else
717 {
718 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
719 for (EthernetFactory::MulticastFaceMap::const_iterator i =
720 factory->getMulticastFaces().begin();
721 i != factory->getMulticastFaces().end();
722 ++i)
723 {
724 multicastFacesToRemove.push_back(i->second);
725 }
726
727 for (std::list<shared_ptr<EthernetFace> >::iterator i =
728 multicastFacesToRemove.begin();
729 i != multicastFacesToRemove.end();
730 ++i)
731 {
732 (*i)->close();
733 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700734 }
735 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600736#else
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700737 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without libpcap, cannot "
738 "process \"ether\" section"));
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700739#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700740}
741
Wentao Shang53df1632014-04-21 12:01:32 -0700742void
743FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
744{
745 // ; the websocket section contains settings of WebSocket faces and channels
746 // websocket
747 // {
748 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
749 // port 9696 ; WebSocket listener port number
750 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
751 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
752 // }
753
754#if defined(HAVE_WEBSOCKET)
755
756 std::string port = "9696";
757 bool needToListen = true;
758 bool enableV4 = true;
759 bool enableV6 = true;
760
761 for (ConfigSection::const_iterator i = configSection.begin();
762 i != configSection.end();
763 ++i)
764 {
765 if (i->first == "port")
766 {
767 port = i->second.get_value<std::string>();
768 try
769 {
770 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
771 NFD_LOG_TRACE("WebSocket port set to " << portNo);
772 }
773 catch (const std::bad_cast& error)
774 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700775 BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
776 i->first + "\" in \"websocket\" section"));
Wentao Shang53df1632014-04-21 12:01:32 -0700777 }
778 }
779 else if (i->first == "listen")
780 {
781 needToListen = parseYesNo(i, i->first, "websocket");
782 }
783 else if (i->first == "enable_v4")
784 {
785 enableV4 = parseYesNo(i, i->first, "websocket");
786 }
787 else if (i->first == "enable_v6")
788 {
789 enableV6 = parseYesNo(i, i->first, "websocket");
790 }
791 else
792 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700793 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
794 i->first + "\" in \"websocket\" section"));
Wentao Shang53df1632014-04-21 12:01:32 -0700795 }
796 }
797
798 if (!enableV4 && !enableV6)
799 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700800 BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
801 " Remove \"websocket\" section to disable WebSocket"
802 " channels or re-enable at least one channel type."));
Wentao Shang53df1632014-04-21 12:01:32 -0700803 }
804
805 if (!enableV4 && enableV6)
806 {
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700807 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel."));
Wentao Shang53df1632014-04-21 12:01:32 -0700808 }
809
810 if (!isDryRun)
811 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300812 if (m_factories.count("websocket") > 0)
813 {
814 return;
815 }
816
Davide Pesaventob499a602014-11-18 22:36:56 +0100817 shared_ptr<WebSocketFactory> factory = make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700818 m_factories.insert(std::make_pair("websocket", factory));
Wentao Shang53df1632014-04-21 12:01:32 -0700819
820 if (enableV6 && enableV4)
821 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600822 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700823 if (needToListen)
824 {
825 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
826 }
827
828 m_factories.insert(std::make_pair("websocket46", factory));
829 }
830 else if (enableV4)
831 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600832 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700833 if (needToListen)
834 {
835 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
836 }
837
838 m_factories.insert(std::make_pair("websocket4", factory));
839 }
840 }
841#else
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700842 BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without WebSocket, "
843 "cannot process \"websocket\" section"));
Wentao Shang53df1632014-04-21 12:01:32 -0700844#endif // HAVE_WEBSOCKET
845}
846
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700847
848void
849FaceManager::onFaceRequest(const Interest& request)
850{
851 const Name& command = request.getName();
852 const size_t commandNComps = command.size();
853
Steve DiBenedettocd4ee5f2014-12-08 16:09:11 -0700854 if (commandNComps <= COMMAND_PREFIX.size())
855 {
856 // command is too short to have a verb
857 NFD_LOG_DEBUG("command result: malformed");
858 sendResponse(command, 400, "Malformed command");
859 return;
860 }
861
862 const Name::Component& verb = command.at(COMMAND_PREFIX.size());
863
864 const auto unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600865 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
866 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700867 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700868 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600869 }
870 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600871 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700872 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700873 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700874 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700875 }
876 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
877 !COMMAND_PREFIX.isPrefixOf(command))
878 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700879 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700880 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700881 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600882 else
883 {
884 validate(request,
885 bind(&FaceManager::onValidatedFaceRequest, this, _1),
886 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
887 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700888}
889
890void
891FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
892{
893 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600894 const Name::Component& verb = command[COMMAND_PREFIX.size()];
895 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700896
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600897 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
898 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700899 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600900 ControlParameters parameters;
901 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700902 {
903 sendResponse(command, 400, "Malformed command");
904 return;
905 }
906
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700907 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600908 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700909 }
910 else
911 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700912 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700913 sendResponse(command, 501, "Unsupported command");
914 }
915
916}
917
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700918void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700919FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
920{
921 m_faceTable.add(newFace);
922
Junxiao Shi6e694322014-04-03 10:27:13 -0700923 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700924}
925
926void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700927FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600928 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700929 const shared_ptr<Face>& newFace)
930{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700931 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600932 parameters.setFaceId(newFace->getId());
Steve DiBenedetto25999282014-05-22 15:25:12 -0600933 parameters.setUri(newFace->getRemoteUri().toString());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700934
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600935 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700936}
937
938void
939FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
940{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700941 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600942 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700943}
944
945void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600946FaceManager::createFace(const Interest& request,
947 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700948{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600949 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600950 ndn::nfd::FaceCreateCommand command;
951
952 if (!validateParameters(command, parameters))
953 {
954 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600955 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600956 return;
957 }
958
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700959 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600960 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700961 {
962 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600963 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700964 return;
965 }
966
Chengyu Fanb94af7c2014-12-17 11:46:47 +0800967 if (!uri.isCanonical())
968 {
969 sendResponse(requestName, 400, "Non-canonical URI");
970 NFD_LOG_TRACE("received non-canonical URI");
971 return;
972 }
973
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700974 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
975 if (factory == m_factories.end())
976 {
977 sendResponse(requestName, 501, "Unsupported protocol");
978 return;
979 }
980
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600981 try
982 {
983 factory->second->createFace(uri,
Yukai Tu7c90e6d2015-07-11 12:21:46 +0800984 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600985 bind(&FaceManager::onCreated,
986 this, requestName, parameters, _1),
987 bind(&FaceManager::onConnectFailed,
988 this, requestName, _1));
989 }
990 catch (const std::runtime_error& error)
991 {
992 std::string errorMessage = "NFD error: ";
993 errorMessage += error.what();
994
995 NFD_LOG_ERROR(errorMessage);
996 sendResponse(requestName, 500, errorMessage);
997 }
998 catch (const std::logic_error& error)
999 {
1000 std::string errorMessage = "NFD error: ";
1001 errorMessage += error.what();
1002
1003 NFD_LOG_ERROR(errorMessage);
1004 sendResponse(requestName, 500, errorMessage);
1005 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001006}
1007
1008
1009void
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001010FaceManager::destroyFace(const Interest& request,
1011 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001012{
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001013 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001014 ndn::nfd::FaceDestroyCommand command;
1015
1016 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001017 {
1018 sendResponse(requestName, 400, "Malformed command");
1019 return;
1020 }
1021
1022 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001023 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001024 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001025 target->close();
1026 }
Steve DiBenedettoba749052014-03-22 19:54:53 -06001027
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001028 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001029
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001030}
1031
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001032void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001033FaceManager::onAddFace(shared_ptr<Face> face)
1034{
Junxiao Shi6e694322014-04-03 10:27:13 -07001035 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001036 notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
1037 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001038
Junxiao Shi6e694322014-04-03 10:27:13 -07001039 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001040}
1041
1042void
1043FaceManager::onRemoveFace(shared_ptr<Face> face)
1044{
Junxiao Shi6e694322014-04-03 10:27:13 -07001045 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001046 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
1047 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001048
Junxiao Shi6e694322014-04-03 10:27:13 -07001049 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001050}
1051
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001052bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001053FaceManager::extractLocalControlParameters(const Interest& request,
1054 ControlParameters& parameters,
1055 ControlCommand& command,
1056 shared_ptr<LocalFace>& outFace,
1057 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001058{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001059 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001060 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001061 sendResponse(request.getName(), 400, "Malformed command");
1062 return false;
1063 }
1064
1065 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
1066
1067 if (!static_cast<bool>(face))
1068 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001069 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001070 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001071 return false;
1072 }
1073 else if (!face->isLocal())
1074 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001075 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
1076 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001077 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001078 return false;
1079 }
1080
1081 outFace = dynamic_pointer_cast<LocalFace>(face);
1082 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
1083
1084 return true;
1085}
1086
1087void
1088FaceManager::enableLocalControl(const Interest& request,
1089 ControlParameters& parameters)
1090{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001091 ndn::nfd::FaceEnableLocalControlCommand command;
1092
1093
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001094 shared_ptr<LocalFace> face;
1095 LocalControlFeature feature;
1096
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001097 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001098 {
1099 face->setLocalControlHeaderFeature(feature, true);
1100 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1101 }
1102}
1103
1104void
1105FaceManager::disableLocalControl(const Interest& request,
1106 ControlParameters& parameters)
1107{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001108 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001109 shared_ptr<LocalFace> face;
1110 LocalControlFeature feature;
1111
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001112 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001113 {
1114 face->setLocalControlHeaderFeature(feature, false);
1115 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1116 }
1117}
1118
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001119void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001120FaceManager::listFaces(const Interest& request)
1121{
1122 const Name& command = request.getName();
1123 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001124
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001125 if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
1126 !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001127 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001128 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001129 sendResponse(command, 400, "Malformed command");
1130 return;
1131 }
1132
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001133 m_faceStatusPublisher.publish();
1134}
1135
1136void
1137FaceManager::listChannels(const Interest& request)
1138{
1139 NFD_LOG_DEBUG("in listChannels");
1140 const Name& command = request.getName();
1141 const size_t commandNComps = command.size();
1142
1143 if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
1144 !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
1145 {
1146 NFD_LOG_DEBUG("command result: malformed");
1147 sendResponse(command, 400, "Malformed command");
1148 return;
1149 }
1150
1151 NFD_LOG_DEBUG("publishing");
1152 m_channelStatusPublisher.publish();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001153}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001154
Chengyu Fan320d2332014-10-29 16:40:33 -06001155void
1156FaceManager::listQueriedFaces(const Interest& request)
1157{
1158 NFD_LOG_DEBUG("in listQueriedFaces");
1159 const Name& query = request.getName();
1160 const size_t queryNComps = query.size();
1161
1162 if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
1163 !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
1164 {
1165 NFD_LOG_DEBUG("query result: malformed");
Chengyu Fanab205c22014-11-18 10:58:41 -07001166 sendNack(query);
Chengyu Fan320d2332014-10-29 16:40:33 -06001167 return;
1168 }
1169
1170 ndn::nfd::FaceQueryFilter faceFilter;
1171 try
1172 {
1173 faceFilter.wireDecode(query[-1].blockFromValue());
1174 }
1175 catch (tlv::Error&)
1176 {
1177 NFD_LOG_DEBUG("query result: malformed filter");
Chengyu Fanab205c22014-11-18 10:58:41 -07001178 sendNack(query);
Chengyu Fan320d2332014-10-29 16:40:33 -06001179 return;
1180 }
1181
1182 FaceQueryStatusPublisher
1183 faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
1184
1185 faceQueryStatusPublisher.publish();
1186}
1187
Alexander Afanasyev5959b012014-06-02 19:18:12 +03001188shared_ptr<ProtocolFactory>
1189FaceManager::findFactory(const std::string& protocol)
1190{
1191 FactoryMap::iterator factory = m_factories.find(protocol);
1192 if (factory != m_factories.end())
1193 return factory->second;
1194 else
1195 return shared_ptr<ProtocolFactory>();
1196}
1197
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001198} // namespace nfd