blob: daba08e3756364fb0f4481e73a01e179d5ab64ea [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)
Vince Lehman5144f822014-07-23 15:12:56 -0700127 , m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
128 , m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
Junxiao Shi15b12e72014-08-09 19:56:24 -0700129 , m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600130 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600131 SIGNED_COMMAND_VERBS +
132 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600133 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600134 UNSIGNED_COMMAND_VERBS +
135 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600136
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700137{
138 face->setInterestFilter("/localhost/nfd/faces",
139 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600140
141 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
142 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700143}
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
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600169 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
170
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700171 for (ConfigSection::const_iterator item = configSection.begin();
172 item != configSection.end();
173 ++item)
174 {
175 if (item->first == "unix")
176 {
177 if (hasSeenUnix)
178 throw Error("Duplicate \"unix\" section");
179 hasSeenUnix = true;
180
181 processSectionUnix(item->second, isDryRun);
182 }
183 else if (item->first == "tcp")
184 {
185 if (hasSeenTcp)
186 throw Error("Duplicate \"tcp\" section");
187 hasSeenTcp = true;
188
189 processSectionTcp(item->second, isDryRun);
190 }
191 else if (item->first == "udp")
192 {
193 if (hasSeenUdp)
194 throw Error("Duplicate \"udp\" section");
195 hasSeenUdp = true;
196
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600197 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700198 }
199 else if (item->first == "ether")
200 {
201 if (hasSeenEther)
202 throw Error("Duplicate \"ether\" section");
203 hasSeenEther = true;
204
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600205 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700206 }
Wentao Shang53df1632014-04-21 12:01:32 -0700207 else if (item->first == "websocket")
208 {
209 if (hasSeenWebSocket)
210 throw Error("Duplicate \"websocket\" section");
211 hasSeenWebSocket = true;
212
213 processSectionWebSocket(item->second, isDryRun);
214 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700215 else
216 {
217 throw Error("Unrecognized option \"" + item->first + "\"");
218 }
219 }
220}
221
222void
223FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
224{
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700225 // ; the unix section contains settings of Unix stream faces and channels
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700226 // unix
227 // {
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700228 // path /var/run/nfd.sock ; Unix stream listener path
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700229 // }
230
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600231#if defined(HAVE_UNIX_SOCKETS)
232
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700233 std::string path = "/var/run/nfd.sock";
234
235 for (ConfigSection::const_iterator i = configSection.begin();
236 i != configSection.end();
237 ++i)
238 {
239 if (i->first == "path")
240 {
241 path = i->second.get_value<std::string>();
242 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700243 else
244 {
245 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
246 }
247 }
248
249 if (!isDryRun)
250 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300251 if (m_factories.count("unix") > 0)
252 {
253 return;
254 // shared_ptr<UnixStreamFactory> factory
255 // = static_pointer_cast<UnixStreamFactory>(m_factories["unix"]);
256 // shared_ptr<UnixStreamChannel> unixChannel = factory->findChannel(path);
257
258 // if (static_cast<bool>(unixChannel))
259 // {
260 // return;
261 // }
262 }
263
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700264 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
265 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
266
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700267 // Should acceptFailed callback be used somehow?
268 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
269 UnixStreamChannel::ConnectFailedCallback());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700270
271 m_factories.insert(std::make_pair("unix", factory));
272 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600273#else
Steve DiBenedettodbcb1a12014-11-17 11:04:21 -0700274 throw ConfigFile::Error("NFD was compiled without Unix sockets support, "
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300275 "cannot process \"unix\" section");
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600276#endif // HAVE_UNIX_SOCKETS
277
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700278}
279
280void
281FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
282{
283 // ; the tcp section contains settings of TCP faces and channels
284 // tcp
285 // {
286 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
287 // port 6363 ; TCP listener port number
288 // }
289
290 std::string port = "6363";
291 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600292 bool enableV4 = true;
293 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700294
295 for (ConfigSection::const_iterator i = configSection.begin();
296 i != configSection.end();
297 ++i)
298 {
299 if (i->first == "port")
300 {
301 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600302 try
303 {
304 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
305 NFD_LOG_TRACE("TCP port set to " << portNo);
306 }
307 catch (const std::bad_cast& error)
308 {
309 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600310 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600311 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700312 }
313 else if (i->first == "listen")
314 {
315 needToListen = parseYesNo(i, i->first, "tcp");
316 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600317 else if (i->first == "enable_v4")
318 {
319 enableV4 = parseYesNo(i, i->first, "tcp");
320 }
321 else if (i->first == "enable_v6")
322 {
323 enableV6 = parseYesNo(i, i->first, "tcp");
324 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700325 else
326 {
327 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
328 }
329 }
330
Steve DiBenedetto95152872014-04-11 12:40:59 -0600331 if (!enableV4 && !enableV6)
332 {
333 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
334 " Remove \"tcp\" section to disable TCP channels or"
335 " re-enable at least one channel type.");
336 }
337
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700338 if (!isDryRun)
339 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300340 if (m_factories.count("tcp") > 0)
341 {
342 return;
343 }
344
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700345 shared_ptr<TcpFactory> factory = ndn::make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600346 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700347
Steve DiBenedetto95152872014-04-11 12:40:59 -0600348 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700349 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600350 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
351 if (needToListen)
352 {
353 // Should acceptFailed callback be used somehow?
354 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
355 TcpChannel::ConnectFailedCallback());
356 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700357
Steve DiBenedetto95152872014-04-11 12:40:59 -0600358 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700359 }
360
Steve DiBenedetto95152872014-04-11 12:40:59 -0600361 if (enableV6)
362 {
363 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
364 if (needToListen)
365 {
366 // Should acceptFailed callback be used somehow?
367 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
368 TcpChannel::ConnectFailedCallback());
369 }
370
371 m_factories.insert(std::make_pair("tcp6", factory));
372 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700373 }
374}
375
376void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600377FaceManager::processSectionUdp(const ConfigSection& configSection,
378 bool isDryRun,
379 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700380{
381 // ; the udp section contains settings of UDP faces and channels
382 // udp
383 // {
384 // port 6363 ; UDP unicast port number
385 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
386 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
387
388 // ; NFD creates one UDP multicast face per NIC
389 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
390 // mcast_port 56363 ; UDP multicast port number
391 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
392 // }
393
394 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600395 bool enableV4 = true;
396 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700397 size_t timeout = 30;
398 size_t keepAliveInterval = 25;
399 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600400 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700401 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600402
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700403
404 for (ConfigSection::const_iterator i = configSection.begin();
405 i != configSection.end();
406 ++i)
407 {
408 if (i->first == "port")
409 {
410 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600411 try
412 {
413 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
414 NFD_LOG_TRACE("UDP port set to " << portNo);
415 }
416 catch (const std::bad_cast& error)
417 {
418 throw ConfigFile::Error("Invalid value for option " +
419 i->first + "\" in \"udp\" section");
420 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700421 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600422 else if (i->first == "enable_v4")
423 {
424 enableV4 = parseYesNo(i, i->first, "udp");
425 }
426 else if (i->first == "enable_v6")
427 {
428 enableV6 = parseYesNo(i, i->first, "udp");
429 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700430 else if (i->first == "idle_timeout")
431 {
432 try
433 {
434 timeout = i->second.get_value<size_t>();
435 }
436 catch (const std::exception& e)
437 {
438 throw ConfigFile::Error("Invalid value for option \"" +
439 i->first + "\" in \"udp\" section");
440 }
441 }
442 else if (i->first == "keep_alive_interval")
443 {
444 try
445 {
446 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700447
448 /// \todo Make use of keepAliveInterval
449 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700450 }
451 catch (const std::exception& e)
452 {
453 throw ConfigFile::Error("Invalid value for option \"" +
454 i->first + "\" in \"udp\" section");
455 }
456 }
457 else if (i->first == "mcast")
458 {
459 useMcast = parseYesNo(i, i->first, "udp");
460 }
461 else if (i->first == "mcast_port")
462 {
463 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600464 try
465 {
466 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
467 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
468 }
469 catch (const std::bad_cast& error)
470 {
471 throw ConfigFile::Error("Invalid value for option " +
472 i->first + "\" in \"udp\" section");
473 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700474 }
475 else if (i->first == "mcast_group")
476 {
477 using namespace boost::asio::ip;
478 mcastGroup = i->second.get_value<std::string>();
479 try
480 {
481 address mcastGroupTest = address::from_string(mcastGroup);
482 if (!mcastGroupTest.is_v4())
483 {
484 throw ConfigFile::Error("Invalid value for option \"" +
485 i->first + "\" in \"udp\" section");
486 }
487 }
488 catch(const std::runtime_error& e)
489 {
490 throw ConfigFile::Error("Invalid value for option \"" +
491 i->first + "\" in \"udp\" section");
492 }
493 }
494 else
495 {
496 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
497 }
498 }
499
Steve DiBenedetto95152872014-04-11 12:40:59 -0600500 if (!enableV4 && !enableV6)
501 {
502 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
503 " Remove \"udp\" section to disable UDP channels or"
504 " re-enable at least one channel type.");
505 }
506 else if (useMcast && !enableV4)
507 {
508 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
509 " have been disabled (conflicting configuration options set)");
510 }
511
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700512 /// \todo what is keep alive interval used for?
513
514 if (!isDryRun)
515 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300516 shared_ptr<UdpFactory> factory;
517 bool isReload = false;
518 if (m_factories.count("udp") > 0) {
519 isReload = true;
520 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
521 }
522 else {
523 factory = ndn::make_shared<UdpFactory>(port);
524 m_factories.insert(std::make_pair("udp", factory));
525 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700526
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300527 if (!isReload && enableV4)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600528 {
529 shared_ptr<UdpChannel> v4Channel =
530 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
531
532 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
533 UdpChannel::ConnectFailedCallback());
534
535 m_factories.insert(std::make_pair("udp4", factory));
536 }
537
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300538 if (!isReload && enableV6)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600539 {
540 shared_ptr<UdpChannel> v6Channel =
541 factory->createChannel("::", port, time::seconds(timeout));
542
543 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
544 UdpChannel::ConnectFailedCallback());
545 m_factories.insert(std::make_pair("udp6", factory));
546 }
547
548 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700549 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200550 std::list<shared_ptr<NetworkInterfaceInfo> > ipv4MulticastInterfaces;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600551 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
552 i != nicList.end();
553 ++i)
554 {
555 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
556 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
557 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200558 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600559 }
560 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200561
562 bool isNicNameNecessary = false;
563
564#if defined(__linux__)
565 if (ipv4MulticastInterfaces.size() > 1)
566 {
567 //On Linux, if we have more than one MulticastUdpFace we need to specify
568 //the name of the interface
569 isNicNameNecessary = true;
570 }
571#endif
572
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300573 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
574 for (UdpFactory::MulticastFaceMap::const_iterator i =
575 factory->getMulticastFaces().begin();
576 i != factory->getMulticastFaces().end();
577 ++i)
578 {
579 multicastFacesToRemove.push_back(i->second);
580 }
581
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200582 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i =
583 ipv4MulticastInterfaces.begin();
584 i != ipv4MulticastInterfaces.end();
585 ++i)
586 {
587 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
588 shared_ptr<MulticastUdpFace> newFace;
589 newFace = factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
590 mcastGroup,
591 mcastPort,
592 isNicNameNecessary ? nic->name : "");
593
594 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300595 multicastFacesToRemove.remove(newFace);
596 }
597
598 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
599 multicastFacesToRemove.begin();
600 i != multicastFacesToRemove.end();
601 ++i)
602 {
603 (*i)->close();
604 }
605 }
606 else
607 {
608 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
609 for (UdpFactory::MulticastFaceMap::const_iterator i =
610 factory->getMulticastFaces().begin();
611 i != factory->getMulticastFaces().end();
612 ++i)
613 {
614 multicastFacesToRemove.push_back(i->second);
615 }
616
617 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
618 multicastFacesToRemove.begin();
619 i != multicastFacesToRemove.end();
620 ++i)
621 {
622 (*i)->close();
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200623 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600624 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700625 }
626}
627
628void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600629FaceManager::processSectionEther(const ConfigSection& configSection,
630 bool isDryRun,
631 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700632{
633 // ; the ether section contains settings of Ethernet faces and channels
634 // ether
635 // {
636 // ; NFD creates one Ethernet multicast face per NIC
637 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
638 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
639 // }
640
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700641#if defined(HAVE_LIBPCAP)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600642
643 using ethernet::Address;
644
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700645 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600646 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700647
648 for (ConfigSection::const_iterator i = configSection.begin();
649 i != configSection.end();
650 ++i)
651 {
652 if (i->first == "mcast")
653 {
654 useMcast = parseYesNo(i, i->first, "ether");
655 }
656
657 else if (i->first == "mcast_group")
658 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600659 mcastGroup = Address::fromString(i->second.get_value<std::string>());
660 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700661 {
662 throw ConfigFile::Error("Invalid value for option \"" +
663 i->first + "\" in \"ether\" section");
664 }
665 }
666 else
667 {
668 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
669 }
670 }
671
672 if (!isDryRun)
673 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300674 shared_ptr<EthernetFactory> factory;
675 if (m_factories.count("ether") > 0) {
676 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
677 }
678 else {
679 factory = ndn::make_shared<EthernetFactory>();
680 m_factories.insert(std::make_pair("ether", factory));
681 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700682
683 if (useMcast)
684 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300685 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
686 for (EthernetFactory::MulticastFaceMap::const_iterator i =
687 factory->getMulticastFaces().begin();
688 i != factory->getMulticastFaces().end();
689 ++i)
690 {
691 multicastFacesToRemove.push_back(i->second);
692 }
693
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600694 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
695 i != nicList.end();
696 ++i)
697 {
698 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
699 if (nic->isUp() && nic->isMulticastCapable())
700 {
701 try
702 {
703 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100704 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700705
706 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300707 multicastFacesToRemove.remove(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600708 }
709 catch (const EthernetFactory::Error& factoryError)
710 {
711 NFD_LOG_ERROR(factoryError.what() << ", continuing");
712 }
713 catch (const EthernetFace::Error& faceError)
714 {
715 NFD_LOG_ERROR(faceError.what() << ", continuing");
716 }
717 }
718 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300719
720 for (std::list<shared_ptr<EthernetFace> >::iterator i =
721 multicastFacesToRemove.begin();
722 i != multicastFacesToRemove.end();
723 ++i)
724 {
725 (*i)->close();
726 }
727 }
728 else
729 {
730 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
731 for (EthernetFactory::MulticastFaceMap::const_iterator i =
732 factory->getMulticastFaces().begin();
733 i != factory->getMulticastFaces().end();
734 ++i)
735 {
736 multicastFacesToRemove.push_back(i->second);
737 }
738
739 for (std::list<shared_ptr<EthernetFace> >::iterator i =
740 multicastFacesToRemove.begin();
741 i != multicastFacesToRemove.end();
742 ++i)
743 {
744 (*i)->close();
745 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700746 }
747 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600748#else
749 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700750#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700751}
752
Wentao Shang53df1632014-04-21 12:01:32 -0700753void
754FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
755{
756 // ; the websocket section contains settings of WebSocket faces and channels
757 // websocket
758 // {
759 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
760 // port 9696 ; WebSocket listener port number
761 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
762 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
763 // }
764
765#if defined(HAVE_WEBSOCKET)
766
767 std::string port = "9696";
768 bool needToListen = true;
769 bool enableV4 = true;
770 bool enableV6 = true;
771
772 for (ConfigSection::const_iterator i = configSection.begin();
773 i != configSection.end();
774 ++i)
775 {
776 if (i->first == "port")
777 {
778 port = i->second.get_value<std::string>();
779 try
780 {
781 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
782 NFD_LOG_TRACE("WebSocket port set to " << portNo);
783 }
784 catch (const std::bad_cast& error)
785 {
786 throw ConfigFile::Error("Invalid value for option " +
787 i->first + "\" in \"websocket\" section");
788 }
789 }
790 else if (i->first == "listen")
791 {
792 needToListen = parseYesNo(i, i->first, "websocket");
793 }
794 else if (i->first == "enable_v4")
795 {
796 enableV4 = parseYesNo(i, i->first, "websocket");
797 }
798 else if (i->first == "enable_v6")
799 {
800 enableV6 = parseYesNo(i, i->first, "websocket");
801 }
802 else
803 {
804 throw ConfigFile::Error("Unrecognized option \"" +
805 i->first + "\" in \"websocket\" section");
806 }
807 }
808
809 if (!enableV4 && !enableV6)
810 {
811 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
812 " Remove \"websocket\" section to disable WebSocket channels or"
813 " re-enable at least one channel type.");
814 }
815
816 if (!enableV4 && enableV6)
817 {
818 throw ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel.");
819 }
820
821 if (!isDryRun)
822 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300823 if (m_factories.count("websocket") > 0)
824 {
825 return;
826 }
827
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700828 shared_ptr<WebSocketFactory> factory = ndn::make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700829 m_factories.insert(std::make_pair("websocket", factory));
Wentao Shang53df1632014-04-21 12:01:32 -0700830
831 if (enableV6 && enableV4)
832 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600833 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700834 if (needToListen)
835 {
836 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
837 }
838
839 m_factories.insert(std::make_pair("websocket46", factory));
840 }
841 else if (enableV4)
842 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600843 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700844 if (needToListen)
845 {
846 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
847 }
848
849 m_factories.insert(std::make_pair("websocket4", factory));
850 }
851 }
852#else
853 throw ConfigFile::Error("NFD was compiled without WebSocket, "
854 "cannot process \"websocket\" section");
855#endif // HAVE_WEBSOCKET
856}
857
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700858
859void
860FaceManager::onFaceRequest(const Interest& request)
861{
862 const Name& command = request.getName();
863 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600864 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700865
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300866 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor =
867 m_unsignedVerbDispatch.find(verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600868 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
869 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700870 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700871 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600872 }
873 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600874 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700875 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700876 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700877 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700878 }
879 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
880 !COMMAND_PREFIX.isPrefixOf(command))
881 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700882 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700883 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700884 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600885 else
886 {
887 validate(request,
888 bind(&FaceManager::onValidatedFaceRequest, this, _1),
889 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
890 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700891}
892
893void
894FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
895{
896 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600897 const Name::Component& verb = command[COMMAND_PREFIX.size()];
898 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700899
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600900 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
901 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700902 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600903 ControlParameters parameters;
904 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700905 {
906 sendResponse(command, 400, "Malformed command");
907 return;
908 }
909
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700910 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600911 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700912 }
913 else
914 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700915 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700916 sendResponse(command, 501, "Unsupported command");
917 }
918
919}
920
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700921void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700922FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
923{
924 m_faceTable.add(newFace);
925
Junxiao Shi6e694322014-04-03 10:27:13 -0700926 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700927}
928
929void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700930FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600931 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700932 const shared_ptr<Face>& newFace)
933{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700934 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600935 parameters.setFaceId(newFace->getId());
Steve DiBenedetto25999282014-05-22 15:25:12 -0600936 parameters.setUri(newFace->getRemoteUri().toString());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700937
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600938 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700939}
940
941void
942FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
943{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700944 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600945 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700946}
947
948void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600949FaceManager::createFace(const Interest& request,
950 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700951{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600952 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600953 ndn::nfd::FaceCreateCommand command;
954
955 if (!validateParameters(command, parameters))
956 {
957 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600958 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600959 return;
960 }
961
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700962 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600963 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700964 {
965 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600966 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700967 return;
968 }
969
970 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
971 if (factory == m_factories.end())
972 {
973 sendResponse(requestName, 501, "Unsupported protocol");
974 return;
975 }
976
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600977 try
978 {
979 factory->second->createFace(uri,
980 bind(&FaceManager::onCreated,
981 this, requestName, parameters, _1),
982 bind(&FaceManager::onConnectFailed,
983 this, requestName, _1));
984 }
985 catch (const std::runtime_error& error)
986 {
987 std::string errorMessage = "NFD error: ";
988 errorMessage += error.what();
989
990 NFD_LOG_ERROR(errorMessage);
991 sendResponse(requestName, 500, errorMessage);
992 }
993 catch (const std::logic_error& error)
994 {
995 std::string errorMessage = "NFD error: ";
996 errorMessage += error.what();
997
998 NFD_LOG_ERROR(errorMessage);
999 sendResponse(requestName, 500, errorMessage);
1000 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001001}
1002
1003
1004void
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001005FaceManager::destroyFace(const Interest& request,
1006 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001007{
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001008 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001009 ndn::nfd::FaceDestroyCommand command;
1010
1011 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001012 {
1013 sendResponse(requestName, 400, "Malformed command");
1014 return;
1015 }
1016
1017 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001018 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001019 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001020 target->close();
1021 }
Steve DiBenedettoba749052014-03-22 19:54:53 -06001022
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001023 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001024
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001025}
1026
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001027void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001028FaceManager::onAddFace(shared_ptr<Face> face)
1029{
Junxiao Shi6e694322014-04-03 10:27:13 -07001030 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001031 notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
1032 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001033
Junxiao Shi6e694322014-04-03 10:27:13 -07001034 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001035}
1036
1037void
1038FaceManager::onRemoveFace(shared_ptr<Face> face)
1039{
Junxiao Shi6e694322014-04-03 10:27:13 -07001040 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001041 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
1042 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001043
Junxiao Shi6e694322014-04-03 10:27:13 -07001044 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001045}
1046
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001047bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001048FaceManager::extractLocalControlParameters(const Interest& request,
1049 ControlParameters& parameters,
1050 ControlCommand& command,
1051 shared_ptr<LocalFace>& outFace,
1052 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001053{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001054 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001055 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001056 sendResponse(request.getName(), 400, "Malformed command");
1057 return false;
1058 }
1059
1060 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
1061
1062 if (!static_cast<bool>(face))
1063 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001064 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001065 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001066 return false;
1067 }
1068 else if (!face->isLocal())
1069 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001070 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
1071 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001072 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001073 return false;
1074 }
1075
1076 outFace = dynamic_pointer_cast<LocalFace>(face);
1077 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
1078
1079 return true;
1080}
1081
1082void
1083FaceManager::enableLocalControl(const Interest& request,
1084 ControlParameters& parameters)
1085{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001086 ndn::nfd::FaceEnableLocalControlCommand command;
1087
1088
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001089 shared_ptr<LocalFace> face;
1090 LocalControlFeature feature;
1091
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001092 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001093 {
1094 face->setLocalControlHeaderFeature(feature, true);
1095 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1096 }
1097}
1098
1099void
1100FaceManager::disableLocalControl(const Interest& request,
1101 ControlParameters& parameters)
1102{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001103 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001104 shared_ptr<LocalFace> face;
1105 LocalControlFeature feature;
1106
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001107 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001108 {
1109 face->setLocalControlHeaderFeature(feature, false);
1110 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1111 }
1112}
1113
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001114void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001115FaceManager::listFaces(const Interest& request)
1116{
1117 const Name& command = request.getName();
1118 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001119
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001120 if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
1121 !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001122 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001123 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001124 sendResponse(command, 400, "Malformed command");
1125 return;
1126 }
1127
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001128 m_faceStatusPublisher.publish();
1129}
1130
1131void
1132FaceManager::listChannels(const Interest& request)
1133{
1134 NFD_LOG_DEBUG("in listChannels");
1135 const Name& command = request.getName();
1136 const size_t commandNComps = command.size();
1137
1138 if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
1139 !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
1140 {
1141 NFD_LOG_DEBUG("command result: malformed");
1142 sendResponse(command, 400, "Malformed command");
1143 return;
1144 }
1145
1146 NFD_LOG_DEBUG("publishing");
1147 m_channelStatusPublisher.publish();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001148}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001149
Chengyu Fan320d2332014-10-29 16:40:33 -06001150void
1151FaceManager::listQueriedFaces(const Interest& request)
1152{
1153 NFD_LOG_DEBUG("in listQueriedFaces");
1154 const Name& query = request.getName();
1155 const size_t queryNComps = query.size();
1156
1157 if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
1158 !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
1159 {
1160 NFD_LOG_DEBUG("query result: malformed");
1161 //sendNack(query);
1162 return;
1163 }
1164
1165 ndn::nfd::FaceQueryFilter faceFilter;
1166 try
1167 {
1168 faceFilter.wireDecode(query[-1].blockFromValue());
1169 }
1170 catch (tlv::Error&)
1171 {
1172 NFD_LOG_DEBUG("query result: malformed filter");
1173 //sendNack(query);
1174 return;
1175 }
1176
1177 FaceQueryStatusPublisher
1178 faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
1179
1180 faceQueryStatusPublisher.publish();
1181}
1182
Alexander Afanasyev5959b012014-06-02 19:18:12 +03001183shared_ptr<ProtocolFactory>
1184FaceManager::findFactory(const std::string& protocol)
1185{
1186 FactoryMap::iterator factory = m_factories.find(protocol);
1187 if (factory != m_factories.end())
1188 return factory->second;
1189 else
1190 return shared_ptr<ProtocolFactory>();
1191}
1192
1193
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001194} // namespace nfd