blob: 3c590f5088a51c07c5a0942cf77568bbbcc3cd3d [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)
176 throw Error("Duplicate \"unix\" section");
177 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)
184 throw Error("Duplicate \"tcp\" section");
185 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)
192 throw Error("Duplicate \"udp\" section");
193 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)
200 throw Error("Duplicate \"ether\" section");
201 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)
208 throw Error("Duplicate \"websocket\" section");
209 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 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100215 throw 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 {
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
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700265 // Should acceptFailed callback be used somehow?
266 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
267 UnixStreamChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700268
269 m_factories.insert(std::make_pair("unix", factory));
270 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600271#else
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700272 throw ConfigFile::Error("NFD was compiled without Unix sockets support, "
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300273 "cannot process \"unix\" section");
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600274#endif // HAVE_UNIX_SOCKETS
275
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700276}
277
278void
279FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
280{
281 // ; the tcp section contains settings of TCP faces and channels
282 // tcp
283 // {
284 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
285 // port 6363 ; TCP listener port number
286 // }
287
288 std::string port = "6363";
289 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600290 bool enableV4 = true;
291 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700292
293 for (ConfigSection::const_iterator i = configSection.begin();
294 i != configSection.end();
295 ++i)
296 {
297 if (i->first == "port")
298 {
299 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600300 try
301 {
302 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
303 NFD_LOG_TRACE("TCP port set to " << portNo);
304 }
305 catch (const std::bad_cast& error)
306 {
307 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600308 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600309 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700310 }
311 else if (i->first == "listen")
312 {
313 needToListen = parseYesNo(i, i->first, "tcp");
314 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600315 else if (i->first == "enable_v4")
316 {
317 enableV4 = parseYesNo(i, i->first, "tcp");
318 }
319 else if (i->first == "enable_v6")
320 {
321 enableV6 = parseYesNo(i, i->first, "tcp");
322 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700323 else
324 {
325 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
326 }
327 }
328
Steve DiBenedetto95152872014-04-11 12:40:59 -0600329 if (!enableV4 && !enableV6)
330 {
331 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
332 " Remove \"tcp\" section to disable TCP channels or"
333 " re-enable at least one channel type.");
334 }
335
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700336 if (!isDryRun)
337 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300338 if (m_factories.count("tcp") > 0)
339 {
340 return;
341 }
342
Davide Pesaventob499a602014-11-18 22:36:56 +0100343 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600344 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700345
Steve DiBenedetto95152872014-04-11 12:40:59 -0600346 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700347 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600348 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
349 if (needToListen)
350 {
351 // Should acceptFailed callback be used somehow?
352 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
353 TcpChannel::ConnectFailedCallback());
354 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700355
Steve DiBenedetto95152872014-04-11 12:40:59 -0600356 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700357 }
358
Steve DiBenedetto95152872014-04-11 12:40:59 -0600359 if (enableV6)
360 {
361 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
362 if (needToListen)
363 {
364 // Should acceptFailed callback be used somehow?
365 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
366 TcpChannel::ConnectFailedCallback());
367 }
368
369 m_factories.insert(std::make_pair("tcp6", factory));
370 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700371 }
372}
373
374void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600375FaceManager::processSectionUdp(const ConfigSection& configSection,
376 bool isDryRun,
Davide Pesaventob499a602014-11-18 22:36:56 +0100377 const std::vector<NetworkInterfaceInfo>& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700378{
379 // ; the udp section contains settings of UDP faces and channels
380 // udp
381 // {
382 // port 6363 ; UDP unicast port number
Chengyu Fanaddecff2015-02-10 14:09:01 -0700383 // idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
384 // keep_alive_interval 25 ; interval (seconds) between keep-alive refreshes
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700385
386 // ; NFD creates one UDP multicast face per NIC
387 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
388 // mcast_port 56363 ; UDP multicast port number
389 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
390 // }
391
392 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600393 bool enableV4 = true;
394 bool enableV6 = true;
Chengyu Fanaddecff2015-02-10 14:09:01 -0700395 size_t timeout = 600;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700396 size_t keepAliveInterval = 25;
397 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600398 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700399 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600400
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700401
402 for (ConfigSection::const_iterator i = configSection.begin();
403 i != configSection.end();
404 ++i)
405 {
406 if (i->first == "port")
407 {
408 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600409 try
410 {
411 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
412 NFD_LOG_TRACE("UDP port set to " << portNo);
413 }
414 catch (const std::bad_cast& error)
415 {
416 throw ConfigFile::Error("Invalid value for option " +
417 i->first + "\" in \"udp\" section");
418 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700419 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600420 else if (i->first == "enable_v4")
421 {
422 enableV4 = parseYesNo(i, i->first, "udp");
423 }
424 else if (i->first == "enable_v6")
425 {
426 enableV6 = parseYesNo(i, i->first, "udp");
427 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700428 else if (i->first == "idle_timeout")
429 {
430 try
431 {
432 timeout = i->second.get_value<size_t>();
433 }
434 catch (const std::exception& e)
435 {
436 throw ConfigFile::Error("Invalid value for option \"" +
437 i->first + "\" in \"udp\" section");
438 }
439 }
440 else if (i->first == "keep_alive_interval")
441 {
442 try
443 {
444 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700445
446 /// \todo Make use of keepAliveInterval
447 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700448 }
449 catch (const std::exception& e)
450 {
451 throw ConfigFile::Error("Invalid value for option \"" +
452 i->first + "\" in \"udp\" section");
453 }
454 }
455 else if (i->first == "mcast")
456 {
457 useMcast = parseYesNo(i, i->first, "udp");
458 }
459 else if (i->first == "mcast_port")
460 {
461 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600462 try
463 {
464 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
465 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
466 }
467 catch (const std::bad_cast& error)
468 {
469 throw ConfigFile::Error("Invalid value for option " +
470 i->first + "\" in \"udp\" section");
471 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700472 }
473 else if (i->first == "mcast_group")
474 {
475 using namespace boost::asio::ip;
476 mcastGroup = i->second.get_value<std::string>();
477 try
478 {
479 address mcastGroupTest = address::from_string(mcastGroup);
480 if (!mcastGroupTest.is_v4())
481 {
482 throw ConfigFile::Error("Invalid value for option \"" +
483 i->first + "\" in \"udp\" section");
484 }
485 }
486 catch(const std::runtime_error& e)
487 {
488 throw ConfigFile::Error("Invalid value for option \"" +
489 i->first + "\" in \"udp\" section");
490 }
491 }
492 else
493 {
494 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
495 }
496 }
497
Steve DiBenedetto95152872014-04-11 12:40:59 -0600498 if (!enableV4 && !enableV6)
499 {
500 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
501 " Remove \"udp\" section to disable UDP channels or"
502 " re-enable at least one channel type.");
503 }
504 else if (useMcast && !enableV4)
505 {
506 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
507 " have been disabled (conflicting configuration options set)");
508 }
509
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700510 /// \todo what is keep alive interval used for?
511
512 if (!isDryRun)
513 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300514 shared_ptr<UdpFactory> factory;
515 bool isReload = false;
516 if (m_factories.count("udp") > 0) {
517 isReload = true;
518 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
519 }
520 else {
Davide Pesaventob499a602014-11-18 22:36:56 +0100521 factory = make_shared<UdpFactory>(port);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300522 m_factories.insert(std::make_pair("udp", factory));
523 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700524
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300525 if (!isReload && enableV4)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600526 {
527 shared_ptr<UdpChannel> v4Channel =
528 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
529
530 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
531 UdpChannel::ConnectFailedCallback());
532
533 m_factories.insert(std::make_pair("udp4", factory));
534 }
535
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300536 if (!isReload && enableV6)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600537 {
538 shared_ptr<UdpChannel> v6Channel =
539 factory->createChannel("::", port, time::seconds(timeout));
540
541 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
542 UdpChannel::ConnectFailedCallback());
543 m_factories.insert(std::make_pair("udp6", factory));
544 }
545
546 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700547 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100548 std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
549 for (const auto& nic : nicList)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600550 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100551 if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty())
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600552 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200553 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600554 }
555 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200556
557 bool isNicNameNecessary = false;
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200558#if defined(__linux__)
559 if (ipv4MulticastInterfaces.size() > 1)
560 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100561 // On Linux if we have more than one MulticastUdpFace
562 // we need to specify the name of the interface
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200563 isNicNameNecessary = true;
564 }
565#endif
566
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300567 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
568 for (UdpFactory::MulticastFaceMap::const_iterator i =
569 factory->getMulticastFaces().begin();
570 i != factory->getMulticastFaces().end();
571 ++i)
572 {
573 multicastFacesToRemove.push_back(i->second);
574 }
575
Davide Pesaventob499a602014-11-18 22:36:56 +0100576 for (const auto& nic : ipv4MulticastInterfaces)
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200577 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200578 shared_ptr<MulticastUdpFace> newFace;
Davide Pesaventob499a602014-11-18 22:36:56 +0100579 newFace = factory->createMulticastFace(nic.ipv4Addresses[0].to_string(),
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200580 mcastGroup,
581 mcastPort,
Davide Pesaventob499a602014-11-18 22:36:56 +0100582 isNicNameNecessary ? nic.name : "");
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200583 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300584 multicastFacesToRemove.remove(newFace);
585 }
586
587 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
588 multicastFacesToRemove.begin();
589 i != multicastFacesToRemove.end();
590 ++i)
591 {
592 (*i)->close();
593 }
594 }
595 else
596 {
597 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
598 for (UdpFactory::MulticastFaceMap::const_iterator i =
599 factory->getMulticastFaces().begin();
600 i != factory->getMulticastFaces().end();
601 ++i)
602 {
603 multicastFacesToRemove.push_back(i->second);
604 }
605
606 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
607 multicastFacesToRemove.begin();
608 i != multicastFacesToRemove.end();
609 ++i)
610 {
611 (*i)->close();
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200612 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600613 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700614 }
615}
616
617void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600618FaceManager::processSectionEther(const ConfigSection& configSection,
619 bool isDryRun,
Davide Pesaventob499a602014-11-18 22:36:56 +0100620 const std::vector<NetworkInterfaceInfo>& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700621{
622 // ; the ether section contains settings of Ethernet faces and channels
623 // ether
624 // {
625 // ; NFD creates one Ethernet multicast face per NIC
626 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
627 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
628 // }
629
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700630#if defined(HAVE_LIBPCAP)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700631 bool useMcast = true;
Davide Pesaventob499a602014-11-18 22:36:56 +0100632 ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700633
634 for (ConfigSection::const_iterator i = configSection.begin();
635 i != configSection.end();
636 ++i)
637 {
638 if (i->first == "mcast")
639 {
640 useMcast = parseYesNo(i, i->first, "ether");
641 }
642
643 else if (i->first == "mcast_group")
644 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100645 mcastGroup = ethernet::Address::fromString(i->second.get_value<std::string>());
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600646 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700647 {
648 throw ConfigFile::Error("Invalid value for option \"" +
649 i->first + "\" in \"ether\" section");
650 }
651 }
652 else
653 {
654 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
655 }
656 }
657
658 if (!isDryRun)
659 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300660 shared_ptr<EthernetFactory> factory;
661 if (m_factories.count("ether") > 0) {
662 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
663 }
664 else {
Davide Pesaventob499a602014-11-18 22:36:56 +0100665 factory = make_shared<EthernetFactory>();
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300666 m_factories.insert(std::make_pair("ether", factory));
667 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700668
669 if (useMcast)
670 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300671 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
672 for (EthernetFactory::MulticastFaceMap::const_iterator i =
673 factory->getMulticastFaces().begin();
674 i != factory->getMulticastFaces().end();
675 ++i)
676 {
677 multicastFacesToRemove.push_back(i->second);
678 }
679
Davide Pesaventob499a602014-11-18 22:36:56 +0100680 for (const auto& nic : nicList)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600681 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100682 if (nic.isUp() && nic.isMulticastCapable())
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600683 {
684 try
685 {
686 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100687 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700688
689 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300690 multicastFacesToRemove.remove(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600691 }
692 catch (const EthernetFactory::Error& factoryError)
693 {
694 NFD_LOG_ERROR(factoryError.what() << ", continuing");
695 }
696 catch (const EthernetFace::Error& faceError)
697 {
698 NFD_LOG_ERROR(faceError.what() << ", continuing");
699 }
700 }
701 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300702
703 for (std::list<shared_ptr<EthernetFace> >::iterator i =
704 multicastFacesToRemove.begin();
705 i != multicastFacesToRemove.end();
706 ++i)
707 {
708 (*i)->close();
709 }
710 }
711 else
712 {
713 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
714 for (EthernetFactory::MulticastFaceMap::const_iterator i =
715 factory->getMulticastFaces().begin();
716 i != factory->getMulticastFaces().end();
717 ++i)
718 {
719 multicastFacesToRemove.push_back(i->second);
720 }
721
722 for (std::list<shared_ptr<EthernetFace> >::iterator i =
723 multicastFacesToRemove.begin();
724 i != multicastFacesToRemove.end();
725 ++i)
726 {
727 (*i)->close();
728 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700729 }
730 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600731#else
732 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700733#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700734}
735
Wentao Shang53df1632014-04-21 12:01:32 -0700736void
737FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
738{
739 // ; the websocket section contains settings of WebSocket faces and channels
740 // websocket
741 // {
742 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
743 // port 9696 ; WebSocket listener port number
744 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
745 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
746 // }
747
748#if defined(HAVE_WEBSOCKET)
749
750 std::string port = "9696";
751 bool needToListen = true;
752 bool enableV4 = true;
753 bool enableV6 = true;
754
755 for (ConfigSection::const_iterator i = configSection.begin();
756 i != configSection.end();
757 ++i)
758 {
759 if (i->first == "port")
760 {
761 port = i->second.get_value<std::string>();
762 try
763 {
764 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
765 NFD_LOG_TRACE("WebSocket port set to " << portNo);
766 }
767 catch (const std::bad_cast& error)
768 {
769 throw ConfigFile::Error("Invalid value for option " +
770 i->first + "\" in \"websocket\" section");
771 }
772 }
773 else if (i->first == "listen")
774 {
775 needToListen = parseYesNo(i, i->first, "websocket");
776 }
777 else if (i->first == "enable_v4")
778 {
779 enableV4 = parseYesNo(i, i->first, "websocket");
780 }
781 else if (i->first == "enable_v6")
782 {
783 enableV6 = parseYesNo(i, i->first, "websocket");
784 }
785 else
786 {
787 throw ConfigFile::Error("Unrecognized option \"" +
788 i->first + "\" in \"websocket\" section");
789 }
790 }
791
792 if (!enableV4 && !enableV6)
793 {
794 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
795 " Remove \"websocket\" section to disable WebSocket channels or"
796 " re-enable at least one channel type.");
797 }
798
799 if (!enableV4 && enableV6)
800 {
801 throw ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel.");
802 }
803
804 if (!isDryRun)
805 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300806 if (m_factories.count("websocket") > 0)
807 {
808 return;
809 }
810
Davide Pesaventob499a602014-11-18 22:36:56 +0100811 shared_ptr<WebSocketFactory> factory = make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700812 m_factories.insert(std::make_pair("websocket", factory));
Wentao Shang53df1632014-04-21 12:01:32 -0700813
814 if (enableV6 && enableV4)
815 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600816 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700817 if (needToListen)
818 {
819 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
820 }
821
822 m_factories.insert(std::make_pair("websocket46", factory));
823 }
824 else if (enableV4)
825 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600826 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700827 if (needToListen)
828 {
829 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
830 }
831
832 m_factories.insert(std::make_pair("websocket4", factory));
833 }
834 }
835#else
836 throw ConfigFile::Error("NFD was compiled without WebSocket, "
837 "cannot process \"websocket\" section");
838#endif // HAVE_WEBSOCKET
839}
840
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700841
842void
843FaceManager::onFaceRequest(const Interest& request)
844{
845 const Name& command = request.getName();
846 const size_t commandNComps = command.size();
847
Steve DiBenedettocd4ee5f2014-12-08 16:09:11 -0700848 if (commandNComps <= COMMAND_PREFIX.size())
849 {
850 // command is too short to have a verb
851 NFD_LOG_DEBUG("command result: malformed");
852 sendResponse(command, 400, "Malformed command");
853 return;
854 }
855
856 const Name::Component& verb = command.at(COMMAND_PREFIX.size());
857
858 const auto unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600859 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
860 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700861 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700862 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600863 }
864 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600865 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700866 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700867 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700868 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700869 }
870 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
871 !COMMAND_PREFIX.isPrefixOf(command))
872 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700873 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700874 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700875 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600876 else
877 {
878 validate(request,
879 bind(&FaceManager::onValidatedFaceRequest, this, _1),
880 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
881 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700882}
883
884void
885FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
886{
887 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600888 const Name::Component& verb = command[COMMAND_PREFIX.size()];
889 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700890
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600891 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
892 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700893 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600894 ControlParameters parameters;
895 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700896 {
897 sendResponse(command, 400, "Malformed command");
898 return;
899 }
900
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700901 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600902 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700903 }
904 else
905 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700906 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700907 sendResponse(command, 501, "Unsupported command");
908 }
909
910}
911
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700912void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700913FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
914{
915 m_faceTable.add(newFace);
916
Junxiao Shi6e694322014-04-03 10:27:13 -0700917 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700918}
919
920void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700921FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600922 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700923 const shared_ptr<Face>& newFace)
924{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700925 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600926 parameters.setFaceId(newFace->getId());
Steve DiBenedetto25999282014-05-22 15:25:12 -0600927 parameters.setUri(newFace->getRemoteUri().toString());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700928
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600929 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700930}
931
932void
933FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
934{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700935 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600936 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700937}
938
939void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600940FaceManager::createFace(const Interest& request,
941 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700942{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600943 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600944 ndn::nfd::FaceCreateCommand command;
945
946 if (!validateParameters(command, parameters))
947 {
948 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600949 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600950 return;
951 }
952
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700953 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600954 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700955 {
956 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600957 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700958 return;
959 }
960
Chengyu Fanb94af7c2014-12-17 11:46:47 +0800961 if (!uri.isCanonical())
962 {
963 sendResponse(requestName, 400, "Non-canonical URI");
964 NFD_LOG_TRACE("received non-canonical URI");
965 return;
966 }
967
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700968 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
969 if (factory == m_factories.end())
970 {
971 sendResponse(requestName, 501, "Unsupported protocol");
972 return;
973 }
974
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600975 try
976 {
977 factory->second->createFace(uri,
978 bind(&FaceManager::onCreated,
979 this, requestName, parameters, _1),
980 bind(&FaceManager::onConnectFailed,
981 this, requestName, _1));
982 }
983 catch (const std::runtime_error& error)
984 {
985 std::string errorMessage = "NFD error: ";
986 errorMessage += error.what();
987
988 NFD_LOG_ERROR(errorMessage);
989 sendResponse(requestName, 500, errorMessage);
990 }
991 catch (const std::logic_error& error)
992 {
993 std::string errorMessage = "NFD error: ";
994 errorMessage += error.what();
995
996 NFD_LOG_ERROR(errorMessage);
997 sendResponse(requestName, 500, errorMessage);
998 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700999}
1000
1001
1002void
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001003FaceManager::destroyFace(const Interest& request,
1004 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001005{
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001006 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001007 ndn::nfd::FaceDestroyCommand command;
1008
1009 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001010 {
1011 sendResponse(requestName, 400, "Malformed command");
1012 return;
1013 }
1014
1015 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001016 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001017 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001018 target->close();
1019 }
Steve DiBenedettoba749052014-03-22 19:54:53 -06001020
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001021 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001022
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001023}
1024
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001025void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001026FaceManager::onAddFace(shared_ptr<Face> face)
1027{
Junxiao Shi6e694322014-04-03 10:27:13 -07001028 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001029 notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
1030 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001031
Junxiao Shi6e694322014-04-03 10:27:13 -07001032 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001033}
1034
1035void
1036FaceManager::onRemoveFace(shared_ptr<Face> face)
1037{
Junxiao Shi6e694322014-04-03 10:27:13 -07001038 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001039 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
1040 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001041
Junxiao Shi6e694322014-04-03 10:27:13 -07001042 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001043}
1044
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001045bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001046FaceManager::extractLocalControlParameters(const Interest& request,
1047 ControlParameters& parameters,
1048 ControlCommand& command,
1049 shared_ptr<LocalFace>& outFace,
1050 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001051{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001052 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001053 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001054 sendResponse(request.getName(), 400, "Malformed command");
1055 return false;
1056 }
1057
1058 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
1059
1060 if (!static_cast<bool>(face))
1061 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001062 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001063 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001064 return false;
1065 }
1066 else if (!face->isLocal())
1067 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001068 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
1069 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001070 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001071 return false;
1072 }
1073
1074 outFace = dynamic_pointer_cast<LocalFace>(face);
1075 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
1076
1077 return true;
1078}
1079
1080void
1081FaceManager::enableLocalControl(const Interest& request,
1082 ControlParameters& parameters)
1083{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001084 ndn::nfd::FaceEnableLocalControlCommand command;
1085
1086
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001087 shared_ptr<LocalFace> face;
1088 LocalControlFeature feature;
1089
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001090 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001091 {
1092 face->setLocalControlHeaderFeature(feature, true);
1093 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1094 }
1095}
1096
1097void
1098FaceManager::disableLocalControl(const Interest& request,
1099 ControlParameters& parameters)
1100{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001101 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001102 shared_ptr<LocalFace> face;
1103 LocalControlFeature feature;
1104
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001105 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001106 {
1107 face->setLocalControlHeaderFeature(feature, false);
1108 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1109 }
1110}
1111
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001112void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001113FaceManager::listFaces(const Interest& request)
1114{
1115 const Name& command = request.getName();
1116 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001117
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001118 if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
1119 !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001120 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001121 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001122 sendResponse(command, 400, "Malformed command");
1123 return;
1124 }
1125
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001126 m_faceStatusPublisher.publish();
1127}
1128
1129void
1130FaceManager::listChannels(const Interest& request)
1131{
1132 NFD_LOG_DEBUG("in listChannels");
1133 const Name& command = request.getName();
1134 const size_t commandNComps = command.size();
1135
1136 if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
1137 !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
1138 {
1139 NFD_LOG_DEBUG("command result: malformed");
1140 sendResponse(command, 400, "Malformed command");
1141 return;
1142 }
1143
1144 NFD_LOG_DEBUG("publishing");
1145 m_channelStatusPublisher.publish();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001146}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001147
Chengyu Fan320d2332014-10-29 16:40:33 -06001148void
1149FaceManager::listQueriedFaces(const Interest& request)
1150{
1151 NFD_LOG_DEBUG("in listQueriedFaces");
1152 const Name& query = request.getName();
1153 const size_t queryNComps = query.size();
1154
1155 if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
1156 !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
1157 {
1158 NFD_LOG_DEBUG("query result: malformed");
Chengyu Fanab205c22014-11-18 10:58:41 -07001159 sendNack(query);
Chengyu Fan320d2332014-10-29 16:40:33 -06001160 return;
1161 }
1162
1163 ndn::nfd::FaceQueryFilter faceFilter;
1164 try
1165 {
1166 faceFilter.wireDecode(query[-1].blockFromValue());
1167 }
1168 catch (tlv::Error&)
1169 {
1170 NFD_LOG_DEBUG("query result: malformed filter");
Chengyu Fanab205c22014-11-18 10:58:41 -07001171 sendNack(query);
Chengyu Fan320d2332014-10-29 16:40:33 -06001172 return;
1173 }
1174
1175 FaceQueryStatusPublisher
1176 faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
1177
1178 faceQueryStatusPublisher.publish();
1179}
1180
Alexander Afanasyev5959b012014-06-02 19:18:12 +03001181shared_ptr<ProtocolFactory>
1182FaceManager::findFactory(const std::string& protocol)
1183{
1184 FactoryMap::iterator factory = m_factories.find(protocol);
1185 if (factory != m_factories.end())
1186 return factory->second;
1187 else
1188 return shared_ptr<ProtocolFactory>();
1189}
1190
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001191} // namespace nfd