blob: f5d849bd4d258595321702eda5e6ccd44aa641bf [file] [log] [blame]
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Steve DiBenedettoef04f272014-06-04 14:28:31 -06003 * Copyright (c) 2014, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Steve DiBenedettoef04f272014-06-04 14:28:31 -060024 */
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070025
26#include "face-manager.hpp"
27
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060028#include "core/logger.hpp"
Steve 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 Afanasyev885a85b2014-04-12 21:01:13 -070041#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070042
Wentao Shang53df1632014-04-21 12:01:32 -070043#ifdef HAVE_WEBSOCKET
44#include "face/websocket-factory.hpp"
45#endif // HAVE_WEBSOCKET
46
Alexander Afanasyev4a771362014-04-24 21:29:33 -070047#include <ndn-cxx/management/nfd-face-event-notification.hpp>
Chengyu Fan320d2332014-10-29 16:40:33 -060048#include <ndn-cxx/management/nfd-face-query-filter.hpp>
Davide Pesavento52a18f92014-04-10 00:55:01 +020049
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070050namespace nfd {
51
52NFD_LOG_INIT("FaceManager");
53
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060054const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070055
56const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
57 FaceManager::COMMAND_PREFIX.size() +
58 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060059 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070060
61const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
62 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070063 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070064
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060065const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070066 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060067 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060068 Name::Component("create"),
69 &FaceManager::createFace
70 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070071
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060072 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060073 Name::Component("destroy"),
74 &FaceManager::destroyFace
75 ),
76
77 SignedVerbAndProcessor(
78 Name::Component("enable-local-control"),
79 &FaceManager::enableLocalControl
80 ),
81
82 SignedVerbAndProcessor(
83 Name::Component("disable-local-control"),
84 &FaceManager::disableLocalControl
85 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070086 };
87
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060088const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
89 {
90 UnsignedVerbAndProcessor(
91 Name::Component("list"),
92 &FaceManager::listFaces
93 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060094
95 UnsignedVerbAndProcessor(
96 Name::Component("events"),
97 &FaceManager::ignoreUnsignedVerb
98 ),
Steve DiBenedettoef04f272014-06-04 14:28:31 -060099
100 UnsignedVerbAndProcessor(
101 Name::Component("channels"),
102 &FaceManager::listChannels
103 ),
Chengyu Fan320d2332014-10-29 16:40:33 -0600104
105 UnsignedVerbAndProcessor(
106 Name::Component("query"),
107 &FaceManager::listQueriedFaces
108 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600109 };
110
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600111const Name FaceManager::FACES_LIST_DATASET_PREFIX("/localhost/nfd/faces/list");
112const size_t FaceManager::FACES_LIST_DATASET_NCOMPS = FACES_LIST_DATASET_PREFIX.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600113
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600114const Name FaceManager::FACE_EVENTS_PREFIX("/localhost/nfd/faces/events");
115
116const Name FaceManager::CHANNELS_LIST_DATASET_PREFIX("/localhost/nfd/faces/channels");
117const size_t FaceManager::CHANNELS_LIST_DATASET_NCOMPS = CHANNELS_LIST_DATASET_PREFIX.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700118
Chengyu Fan320d2332014-10-29 16:40:33 -0600119const Name FaceManager::FACES_QUERY_DATASET_PREFIX("/localhost/nfd/faces/query");
120const size_t FaceManager::FACES_QUERY_DATASET_NCOMPS = FACES_QUERY_DATASET_PREFIX.size() + 1;
121
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700122FaceManager::FaceManager(FaceTable& faceTable,
Vince Lehman5144f822014-07-23 15:12:56 -0700123 shared_ptr<InternalFace> face,
124 ndn::KeyChain& keyChain)
125 : ManagerBase(face, FACE_MANAGER_PRIVILEGE, keyChain)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700126 , m_faceTable(faceTable)
Junxiao Shi1e064172014-12-14 19:37:46 -0700127 , m_faceAddConn(m_faceTable.onAdd.connect(bind(&FaceManager::onAddFace, this, _1)))
128 , m_faceRemoveConn(m_faceTable.onRemove.connect(bind(&FaceManager::onRemoveFace, this, _1)))
Vince Lehman5144f822014-07-23 15:12:56 -0700129 , m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
130 , m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
Junxiao Shi15b12e72014-08-09 19:56:24 -0700131 , m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600132 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600133 SIGNED_COMMAND_VERBS +
134 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600135 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600136 UNSIGNED_COMMAND_VERBS +
137 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600138
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700139{
140 face->setInterestFilter("/localhost/nfd/faces",
141 bind(&FaceManager::onFaceRequest, this, _2));
142}
143
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600144FaceManager::~FaceManager()
145{
146
147}
148
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700149void
150FaceManager::setConfigFile(ConfigFile& configFile)
151{
152 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600153 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700154}
155
156
157void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600158FaceManager::onConfig(const ConfigSection& configSection,
159 bool isDryRun,
160 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700161{
162 bool hasSeenUnix = false;
163 bool hasSeenTcp = false;
164 bool hasSeenUdp = false;
165 bool hasSeenEther = false;
Wentao Shang53df1632014-04-21 12:01:32 -0700166 bool hasSeenWebSocket = false;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700167
Davide Pesaventob499a602014-11-18 22:36:56 +0100168 const std::vector<NetworkInterfaceInfo> nicList(listNetworkInterfaces());
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600169
Davide Pesaventob499a602014-11-18 22:36:56 +0100170 for (const auto& item : configSection)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700171 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100172 if (item.first == "unix")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700173 {
174 if (hasSeenUnix)
175 throw Error("Duplicate \"unix\" section");
176 hasSeenUnix = true;
177
Davide Pesaventob499a602014-11-18 22:36:56 +0100178 processSectionUnix(item.second, isDryRun);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700179 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100180 else if (item.first == "tcp")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700181 {
182 if (hasSeenTcp)
183 throw Error("Duplicate \"tcp\" section");
184 hasSeenTcp = true;
185
Davide Pesaventob499a602014-11-18 22:36:56 +0100186 processSectionTcp(item.second, isDryRun);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700187 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100188 else if (item.first == "udp")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700189 {
190 if (hasSeenUdp)
191 throw Error("Duplicate \"udp\" section");
192 hasSeenUdp = true;
193
Davide Pesaventob499a602014-11-18 22:36:56 +0100194 processSectionUdp(item.second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700195 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100196 else if (item.first == "ether")
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700197 {
198 if (hasSeenEther)
199 throw Error("Duplicate \"ether\" section");
200 hasSeenEther = true;
201
Davide Pesaventob499a602014-11-18 22:36:56 +0100202 processSectionEther(item.second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700203 }
Davide Pesaventob499a602014-11-18 22:36:56 +0100204 else if (item.first == "websocket")
Wentao Shang53df1632014-04-21 12:01:32 -0700205 {
206 if (hasSeenWebSocket)
207 throw Error("Duplicate \"websocket\" section");
208 hasSeenWebSocket = true;
209
Davide Pesaventob499a602014-11-18 22:36:56 +0100210 processSectionWebSocket(item.second, isDryRun);
Wentao Shang53df1632014-04-21 12:01:32 -0700211 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700212 else
213 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100214 throw Error("Unrecognized option \"" + item.first + "\"");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700215 }
216 }
217}
218
219void
220FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
221{
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700222 // ; the unix section contains settings of Unix stream faces and channels
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700223 // unix
224 // {
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700225 // path /var/run/nfd.sock ; Unix stream listener path
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700226 // }
227
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600228#if defined(HAVE_UNIX_SOCKETS)
229
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700230 std::string path = "/var/run/nfd.sock";
231
232 for (ConfigSection::const_iterator i = configSection.begin();
233 i != configSection.end();
234 ++i)
235 {
236 if (i->first == "path")
237 {
238 path = i->second.get_value<std::string>();
239 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700240 else
241 {
242 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
243 }
244 }
245
246 if (!isDryRun)
247 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300248 if (m_factories.count("unix") > 0)
249 {
250 return;
251 // shared_ptr<UnixStreamFactory> factory
252 // = static_pointer_cast<UnixStreamFactory>(m_factories["unix"]);
253 // shared_ptr<UnixStreamChannel> unixChannel = factory->findChannel(path);
254
255 // if (static_cast<bool>(unixChannel))
256 // {
257 // return;
258 // }
259 }
260
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700261 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
262 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
263
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700264 // Should acceptFailed callback be used somehow?
265 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
266 UnixStreamChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700267
268 m_factories.insert(std::make_pair("unix", factory));
269 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600270#else
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700271 throw ConfigFile::Error("NFD was compiled without Unix sockets support, "
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300272 "cannot process \"unix\" section");
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600273#endif // HAVE_UNIX_SOCKETS
274
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700275}
276
277void
278FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
279{
280 // ; the tcp section contains settings of TCP faces and channels
281 // tcp
282 // {
283 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
284 // port 6363 ; TCP listener port number
285 // }
286
287 std::string port = "6363";
288 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600289 bool enableV4 = true;
290 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700291
292 for (ConfigSection::const_iterator i = configSection.begin();
293 i != configSection.end();
294 ++i)
295 {
296 if (i->first == "port")
297 {
298 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600299 try
300 {
301 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
302 NFD_LOG_TRACE("TCP port set to " << portNo);
303 }
304 catch (const std::bad_cast& error)
305 {
306 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600307 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600308 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700309 }
310 else if (i->first == "listen")
311 {
312 needToListen = parseYesNo(i, i->first, "tcp");
313 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600314 else if (i->first == "enable_v4")
315 {
316 enableV4 = parseYesNo(i, i->first, "tcp");
317 }
318 else if (i->first == "enable_v6")
319 {
320 enableV6 = parseYesNo(i, i->first, "tcp");
321 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700322 else
323 {
324 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
325 }
326 }
327
Steve DiBenedetto95152872014-04-11 12:40:59 -0600328 if (!enableV4 && !enableV6)
329 {
330 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
331 " Remove \"tcp\" section to disable TCP channels or"
332 " re-enable at least one channel type.");
333 }
334
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700335 if (!isDryRun)
336 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300337 if (m_factories.count("tcp") > 0)
338 {
339 return;
340 }
341
Davide Pesaventob499a602014-11-18 22:36:56 +0100342 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600343 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700344
Steve DiBenedetto95152872014-04-11 12:40:59 -0600345 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700346 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600347 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
348 if (needToListen)
349 {
350 // Should acceptFailed callback be used somehow?
351 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
352 TcpChannel::ConnectFailedCallback());
353 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700354
Steve DiBenedetto95152872014-04-11 12:40:59 -0600355 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700356 }
357
Steve DiBenedetto95152872014-04-11 12:40:59 -0600358 if (enableV6)
359 {
360 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
361 if (needToListen)
362 {
363 // Should acceptFailed callback be used somehow?
364 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
365 TcpChannel::ConnectFailedCallback());
366 }
367
368 m_factories.insert(std::make_pair("tcp6", factory));
369 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700370 }
371}
372
373void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600374FaceManager::processSectionUdp(const ConfigSection& configSection,
375 bool isDryRun,
Davide Pesaventob499a602014-11-18 22:36:56 +0100376 const std::vector<NetworkInterfaceInfo>& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700377{
378 // ; the udp section contains settings of UDP faces and channels
379 // udp
380 // {
381 // port 6363 ; UDP unicast port number
382 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
383 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
384
385 // ; NFD creates one UDP multicast face per NIC
386 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
387 // mcast_port 56363 ; UDP multicast port number
388 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
389 // }
390
391 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600392 bool enableV4 = true;
393 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700394 size_t timeout = 30;
395 size_t keepAliveInterval = 25;
396 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600397 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700398 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600399
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700400
401 for (ConfigSection::const_iterator i = configSection.begin();
402 i != configSection.end();
403 ++i)
404 {
405 if (i->first == "port")
406 {
407 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600408 try
409 {
410 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
411 NFD_LOG_TRACE("UDP port set to " << portNo);
412 }
413 catch (const std::bad_cast& error)
414 {
415 throw ConfigFile::Error("Invalid value for option " +
416 i->first + "\" in \"udp\" section");
417 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700418 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600419 else if (i->first == "enable_v4")
420 {
421 enableV4 = parseYesNo(i, i->first, "udp");
422 }
423 else if (i->first == "enable_v6")
424 {
425 enableV6 = parseYesNo(i, i->first, "udp");
426 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700427 else if (i->first == "idle_timeout")
428 {
429 try
430 {
431 timeout = i->second.get_value<size_t>();
432 }
433 catch (const std::exception& e)
434 {
435 throw ConfigFile::Error("Invalid value for option \"" +
436 i->first + "\" in \"udp\" section");
437 }
438 }
439 else if (i->first == "keep_alive_interval")
440 {
441 try
442 {
443 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700444
445 /// \todo Make use of keepAliveInterval
446 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700447 }
448 catch (const std::exception& e)
449 {
450 throw ConfigFile::Error("Invalid value for option \"" +
451 i->first + "\" in \"udp\" section");
452 }
453 }
454 else if (i->first == "mcast")
455 {
456 useMcast = parseYesNo(i, i->first, "udp");
457 }
458 else if (i->first == "mcast_port")
459 {
460 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600461 try
462 {
463 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
464 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
465 }
466 catch (const std::bad_cast& error)
467 {
468 throw ConfigFile::Error("Invalid value for option " +
469 i->first + "\" in \"udp\" section");
470 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700471 }
472 else if (i->first == "mcast_group")
473 {
474 using namespace boost::asio::ip;
475 mcastGroup = i->second.get_value<std::string>();
476 try
477 {
478 address mcastGroupTest = address::from_string(mcastGroup);
479 if (!mcastGroupTest.is_v4())
480 {
481 throw ConfigFile::Error("Invalid value for option \"" +
482 i->first + "\" in \"udp\" section");
483 }
484 }
485 catch(const std::runtime_error& e)
486 {
487 throw ConfigFile::Error("Invalid value for option \"" +
488 i->first + "\" in \"udp\" section");
489 }
490 }
491 else
492 {
493 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
494 }
495 }
496
Steve DiBenedetto95152872014-04-11 12:40:59 -0600497 if (!enableV4 && !enableV6)
498 {
499 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
500 " Remove \"udp\" section to disable UDP channels or"
501 " re-enable at least one channel type.");
502 }
503 else if (useMcast && !enableV4)
504 {
505 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
506 " have been disabled (conflicting configuration options set)");
507 }
508
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700509 /// \todo what is keep alive interval used for?
510
511 if (!isDryRun)
512 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300513 shared_ptr<UdpFactory> factory;
514 bool isReload = false;
515 if (m_factories.count("udp") > 0) {
516 isReload = true;
517 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
518 }
519 else {
Davide Pesaventob499a602014-11-18 22:36:56 +0100520 factory = make_shared<UdpFactory>(port);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300521 m_factories.insert(std::make_pair("udp", factory));
522 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700523
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300524 if (!isReload && enableV4)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600525 {
526 shared_ptr<UdpChannel> v4Channel =
527 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
528
529 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
530 UdpChannel::ConnectFailedCallback());
531
532 m_factories.insert(std::make_pair("udp4", factory));
533 }
534
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300535 if (!isReload && enableV6)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600536 {
537 shared_ptr<UdpChannel> v6Channel =
538 factory->createChannel("::", port, time::seconds(timeout));
539
540 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
541 UdpChannel::ConnectFailedCallback());
542 m_factories.insert(std::make_pair("udp6", factory));
543 }
544
545 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700546 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100547 std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
548 for (const auto& nic : nicList)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600549 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100550 if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty())
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600551 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200552 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600553 }
554 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200555
556 bool isNicNameNecessary = false;
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200557#if defined(__linux__)
558 if (ipv4MulticastInterfaces.size() > 1)
559 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100560 // On Linux if we have more than one MulticastUdpFace
561 // we need to specify the name of the interface
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200562 isNicNameNecessary = true;
563 }
564#endif
565
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300566 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
567 for (UdpFactory::MulticastFaceMap::const_iterator i =
568 factory->getMulticastFaces().begin();
569 i != factory->getMulticastFaces().end();
570 ++i)
571 {
572 multicastFacesToRemove.push_back(i->second);
573 }
574
Davide Pesaventob499a602014-11-18 22:36:56 +0100575 for (const auto& nic : ipv4MulticastInterfaces)
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200576 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200577 shared_ptr<MulticastUdpFace> newFace;
Davide Pesaventob499a602014-11-18 22:36:56 +0100578 newFace = factory->createMulticastFace(nic.ipv4Addresses[0].to_string(),
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200579 mcastGroup,
580 mcastPort,
Davide Pesaventob499a602014-11-18 22:36:56 +0100581 isNicNameNecessary ? nic.name : "");
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200582 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300583 multicastFacesToRemove.remove(newFace);
584 }
585
586 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
587 multicastFacesToRemove.begin();
588 i != multicastFacesToRemove.end();
589 ++i)
590 {
591 (*i)->close();
592 }
593 }
594 else
595 {
596 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
597 for (UdpFactory::MulticastFaceMap::const_iterator i =
598 factory->getMulticastFaces().begin();
599 i != factory->getMulticastFaces().end();
600 ++i)
601 {
602 multicastFacesToRemove.push_back(i->second);
603 }
604
605 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
606 multicastFacesToRemove.begin();
607 i != multicastFacesToRemove.end();
608 ++i)
609 {
610 (*i)->close();
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200611 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600612 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700613 }
614}
615
616void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600617FaceManager::processSectionEther(const ConfigSection& configSection,
618 bool isDryRun,
Davide Pesaventob499a602014-11-18 22:36:56 +0100619 const std::vector<NetworkInterfaceInfo>& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700620{
621 // ; the ether section contains settings of Ethernet faces and channels
622 // ether
623 // {
624 // ; NFD creates one Ethernet multicast face per NIC
625 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
626 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
627 // }
628
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700629#if defined(HAVE_LIBPCAP)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700630 bool useMcast = true;
Davide Pesaventob499a602014-11-18 22:36:56 +0100631 ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700632
633 for (ConfigSection::const_iterator i = configSection.begin();
634 i != configSection.end();
635 ++i)
636 {
637 if (i->first == "mcast")
638 {
639 useMcast = parseYesNo(i, i->first, "ether");
640 }
641
642 else if (i->first == "mcast_group")
643 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100644 mcastGroup = ethernet::Address::fromString(i->second.get_value<std::string>());
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600645 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700646 {
647 throw ConfigFile::Error("Invalid value for option \"" +
648 i->first + "\" in \"ether\" section");
649 }
650 }
651 else
652 {
653 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
654 }
655 }
656
657 if (!isDryRun)
658 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300659 shared_ptr<EthernetFactory> factory;
660 if (m_factories.count("ether") > 0) {
661 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
662 }
663 else {
Davide Pesaventob499a602014-11-18 22:36:56 +0100664 factory = make_shared<EthernetFactory>();
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300665 m_factories.insert(std::make_pair("ether", factory));
666 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700667
668 if (useMcast)
669 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300670 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
671 for (EthernetFactory::MulticastFaceMap::const_iterator i =
672 factory->getMulticastFaces().begin();
673 i != factory->getMulticastFaces().end();
674 ++i)
675 {
676 multicastFacesToRemove.push_back(i->second);
677 }
678
Davide Pesaventob499a602014-11-18 22:36:56 +0100679 for (const auto& nic : nicList)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600680 {
Davide Pesaventob499a602014-11-18 22:36:56 +0100681 if (nic.isUp() && nic.isMulticastCapable())
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600682 {
683 try
684 {
685 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100686 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700687
688 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300689 multicastFacesToRemove.remove(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600690 }
691 catch (const EthernetFactory::Error& factoryError)
692 {
693 NFD_LOG_ERROR(factoryError.what() << ", continuing");
694 }
695 catch (const EthernetFace::Error& faceError)
696 {
697 NFD_LOG_ERROR(faceError.what() << ", continuing");
698 }
699 }
700 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300701
702 for (std::list<shared_ptr<EthernetFace> >::iterator i =
703 multicastFacesToRemove.begin();
704 i != multicastFacesToRemove.end();
705 ++i)
706 {
707 (*i)->close();
708 }
709 }
710 else
711 {
712 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
713 for (EthernetFactory::MulticastFaceMap::const_iterator i =
714 factory->getMulticastFaces().begin();
715 i != factory->getMulticastFaces().end();
716 ++i)
717 {
718 multicastFacesToRemove.push_back(i->second);
719 }
720
721 for (std::list<shared_ptr<EthernetFace> >::iterator i =
722 multicastFacesToRemove.begin();
723 i != multicastFacesToRemove.end();
724 ++i)
725 {
726 (*i)->close();
727 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700728 }
729 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600730#else
731 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700732#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700733}
734
Wentao Shang53df1632014-04-21 12:01:32 -0700735void
736FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
737{
738 // ; the websocket section contains settings of WebSocket faces and channels
739 // websocket
740 // {
741 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
742 // port 9696 ; WebSocket listener port number
743 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
744 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
745 // }
746
747#if defined(HAVE_WEBSOCKET)
748
749 std::string port = "9696";
750 bool needToListen = true;
751 bool enableV4 = true;
752 bool enableV6 = true;
753
754 for (ConfigSection::const_iterator i = configSection.begin();
755 i != configSection.end();
756 ++i)
757 {
758 if (i->first == "port")
759 {
760 port = i->second.get_value<std::string>();
761 try
762 {
763 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
764 NFD_LOG_TRACE("WebSocket port set to " << portNo);
765 }
766 catch (const std::bad_cast& error)
767 {
768 throw ConfigFile::Error("Invalid value for option " +
769 i->first + "\" in \"websocket\" section");
770 }
771 }
772 else if (i->first == "listen")
773 {
774 needToListen = parseYesNo(i, i->first, "websocket");
775 }
776 else if (i->first == "enable_v4")
777 {
778 enableV4 = parseYesNo(i, i->first, "websocket");
779 }
780 else if (i->first == "enable_v6")
781 {
782 enableV6 = parseYesNo(i, i->first, "websocket");
783 }
784 else
785 {
786 throw ConfigFile::Error("Unrecognized option \"" +
787 i->first + "\" in \"websocket\" section");
788 }
789 }
790
791 if (!enableV4 && !enableV6)
792 {
793 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
794 " Remove \"websocket\" section to disable WebSocket channels or"
795 " re-enable at least one channel type.");
796 }
797
798 if (!enableV4 && enableV6)
799 {
800 throw ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel.");
801 }
802
803 if (!isDryRun)
804 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300805 if (m_factories.count("websocket") > 0)
806 {
807 return;
808 }
809
Davide Pesaventob499a602014-11-18 22:36:56 +0100810 shared_ptr<WebSocketFactory> factory = make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700811 m_factories.insert(std::make_pair("websocket", factory));
Wentao Shang53df1632014-04-21 12:01:32 -0700812
813 if (enableV6 && enableV4)
814 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600815 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700816 if (needToListen)
817 {
818 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
819 }
820
821 m_factories.insert(std::make_pair("websocket46", factory));
822 }
823 else if (enableV4)
824 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600825 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700826 if (needToListen)
827 {
828 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
829 }
830
831 m_factories.insert(std::make_pair("websocket4", factory));
832 }
833 }
834#else
835 throw ConfigFile::Error("NFD was compiled without WebSocket, "
836 "cannot process \"websocket\" section");
837#endif // HAVE_WEBSOCKET
838}
839
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700840
841void
842FaceManager::onFaceRequest(const Interest& request)
843{
844 const Name& command = request.getName();
845 const size_t commandNComps = command.size();
846
Steve DiBenedettocd4ee5f2014-12-08 16:09:11 -0700847 if (commandNComps <= COMMAND_PREFIX.size())
848 {
849 // command is too short to have a verb
850 NFD_LOG_DEBUG("command result: malformed");
851 sendResponse(command, 400, "Malformed command");
852 return;
853 }
854
855 const Name::Component& verb = command.at(COMMAND_PREFIX.size());
856
857 const auto unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600858 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
859 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700860 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700861 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600862 }
863 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600864 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700865 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700866 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700867 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700868 }
869 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
870 !COMMAND_PREFIX.isPrefixOf(command))
871 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700872 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700873 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700874 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600875 else
876 {
877 validate(request,
878 bind(&FaceManager::onValidatedFaceRequest, this, _1),
879 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
880 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700881}
882
883void
884FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
885{
886 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600887 const Name::Component& verb = command[COMMAND_PREFIX.size()];
888 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700889
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600890 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
891 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700892 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600893 ControlParameters parameters;
894 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700895 {
896 sendResponse(command, 400, "Malformed command");
897 return;
898 }
899
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700900 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600901 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700902 }
903 else
904 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700905 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700906 sendResponse(command, 501, "Unsupported command");
907 }
908
909}
910
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700911void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700912FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
913{
914 m_faceTable.add(newFace);
915
Junxiao Shi6e694322014-04-03 10:27:13 -0700916 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700917}
918
919void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700920FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600921 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700922 const shared_ptr<Face>& newFace)
923{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700924 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600925 parameters.setFaceId(newFace->getId());
Steve DiBenedetto25999282014-05-22 15:25:12 -0600926 parameters.setUri(newFace->getRemoteUri().toString());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700927
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600928 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700929}
930
931void
932FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
933{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700934 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600935 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700936}
937
938void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600939FaceManager::createFace(const Interest& request,
940 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700941{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600942 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600943 ndn::nfd::FaceCreateCommand command;
944
945 if (!validateParameters(command, parameters))
946 {
947 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600948 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600949 return;
950 }
951
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700952 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600953 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700954 {
955 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600956 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700957 return;
958 }
959
Chengyu Fanb94af7c2014-12-17 11:46:47 +0800960 if (!uri.isCanonical())
961 {
962 sendResponse(requestName, 400, "Non-canonical URI");
963 NFD_LOG_TRACE("received non-canonical URI");
964 return;
965 }
966
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700967 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
968 if (factory == m_factories.end())
969 {
970 sendResponse(requestName, 501, "Unsupported protocol");
971 return;
972 }
973
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600974 try
975 {
976 factory->second->createFace(uri,
977 bind(&FaceManager::onCreated,
978 this, requestName, parameters, _1),
979 bind(&FaceManager::onConnectFailed,
980 this, requestName, _1));
981 }
982 catch (const std::runtime_error& error)
983 {
984 std::string errorMessage = "NFD error: ";
985 errorMessage += error.what();
986
987 NFD_LOG_ERROR(errorMessage);
988 sendResponse(requestName, 500, errorMessage);
989 }
990 catch (const std::logic_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 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700998}
999
1000
1001void
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001002FaceManager::destroyFace(const Interest& request,
1003 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001004{
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001005 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001006 ndn::nfd::FaceDestroyCommand command;
1007
1008 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001009 {
1010 sendResponse(requestName, 400, "Malformed command");
1011 return;
1012 }
1013
1014 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001015 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001016 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001017 target->close();
1018 }
Steve DiBenedettoba749052014-03-22 19:54:53 -06001019
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001020 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001021
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001022}
1023
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001024void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001025FaceManager::onAddFace(shared_ptr<Face> face)
1026{
Junxiao Shi6e694322014-04-03 10:27:13 -07001027 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001028 notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
1029 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001030
Junxiao Shi6e694322014-04-03 10:27:13 -07001031 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001032}
1033
1034void
1035FaceManager::onRemoveFace(shared_ptr<Face> face)
1036{
Junxiao Shi6e694322014-04-03 10:27:13 -07001037 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001038 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
1039 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001040
Junxiao Shi6e694322014-04-03 10:27:13 -07001041 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001042}
1043
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001044bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001045FaceManager::extractLocalControlParameters(const Interest& request,
1046 ControlParameters& parameters,
1047 ControlCommand& command,
1048 shared_ptr<LocalFace>& outFace,
1049 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001050{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001051 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001052 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001053 sendResponse(request.getName(), 400, "Malformed command");
1054 return false;
1055 }
1056
1057 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
1058
1059 if (!static_cast<bool>(face))
1060 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001061 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001062 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001063 return false;
1064 }
1065 else if (!face->isLocal())
1066 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001067 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
1068 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001069 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001070 return false;
1071 }
1072
1073 outFace = dynamic_pointer_cast<LocalFace>(face);
1074 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
1075
1076 return true;
1077}
1078
1079void
1080FaceManager::enableLocalControl(const Interest& request,
1081 ControlParameters& parameters)
1082{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001083 ndn::nfd::FaceEnableLocalControlCommand command;
1084
1085
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001086 shared_ptr<LocalFace> face;
1087 LocalControlFeature feature;
1088
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001089 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001090 {
1091 face->setLocalControlHeaderFeature(feature, true);
1092 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1093 }
1094}
1095
1096void
1097FaceManager::disableLocalControl(const Interest& request,
1098 ControlParameters& parameters)
1099{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001100 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001101 shared_ptr<LocalFace> face;
1102 LocalControlFeature feature;
1103
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001104 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001105 {
1106 face->setLocalControlHeaderFeature(feature, false);
1107 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1108 }
1109}
1110
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001111void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001112FaceManager::listFaces(const Interest& request)
1113{
1114 const Name& command = request.getName();
1115 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001116
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001117 if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
1118 !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001119 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001120 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001121 sendResponse(command, 400, "Malformed command");
1122 return;
1123 }
1124
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001125 m_faceStatusPublisher.publish();
1126}
1127
1128void
1129FaceManager::listChannels(const Interest& request)
1130{
1131 NFD_LOG_DEBUG("in listChannels");
1132 const Name& command = request.getName();
1133 const size_t commandNComps = command.size();
1134
1135 if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
1136 !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
1137 {
1138 NFD_LOG_DEBUG("command result: malformed");
1139 sendResponse(command, 400, "Malformed command");
1140 return;
1141 }
1142
1143 NFD_LOG_DEBUG("publishing");
1144 m_channelStatusPublisher.publish();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001145}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001146
Chengyu Fan320d2332014-10-29 16:40:33 -06001147void
1148FaceManager::listQueriedFaces(const Interest& request)
1149{
1150 NFD_LOG_DEBUG("in listQueriedFaces");
1151 const Name& query = request.getName();
1152 const size_t queryNComps = query.size();
1153
1154 if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
1155 !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
1156 {
1157 NFD_LOG_DEBUG("query result: malformed");
Chengyu Fanab205c22014-11-18 10:58:41 -07001158 sendNack(query);
Chengyu Fan320d2332014-10-29 16:40:33 -06001159 return;
1160 }
1161
1162 ndn::nfd::FaceQueryFilter faceFilter;
1163 try
1164 {
1165 faceFilter.wireDecode(query[-1].blockFromValue());
1166 }
1167 catch (tlv::Error&)
1168 {
1169 NFD_LOG_DEBUG("query result: malformed filter");
Chengyu Fanab205c22014-11-18 10:58:41 -07001170 sendNack(query);
Chengyu Fan320d2332014-10-29 16:40:33 -06001171 return;
1172 }
1173
1174 FaceQueryStatusPublisher
1175 faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
1176
1177 faceQueryStatusPublisher.publish();
1178}
1179
Alexander Afanasyev5959b012014-06-02 19:18:12 +03001180shared_ptr<ProtocolFactory>
1181FaceManager::findFactory(const std::string& protocol)
1182{
1183 FactoryMap::iterator factory = m_factories.find(protocol);
1184 if (factory != m_factories.end())
1185 return factory->second;
1186 else
1187 return shared_ptr<ProtocolFactory>();
1188}
1189
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001190} // namespace nfd