blob: e4286e859dd583e780ee3a9474401a3e6b8712e4 [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{
225 // ; the unix section contains settings of UNIX stream faces and channels
226 // unix
227 // {
228 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
229 // path /var/run/nfd.sock ; UNIX stream listener path
230 // }
231
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600232#if defined(HAVE_UNIX_SOCKETS)
233
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700234 bool needToListen = true;
235 std::string path = "/var/run/nfd.sock";
236
237 for (ConfigSection::const_iterator i = configSection.begin();
238 i != configSection.end();
239 ++i)
240 {
241 if (i->first == "path")
242 {
243 path = i->second.get_value<std::string>();
244 }
245 else if (i->first == "listen")
246 {
247 needToListen = parseYesNo(i, i->first, "unix");
248 }
249 else
250 {
251 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
252 }
253 }
254
255 if (!isDryRun)
256 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300257 if (m_factories.count("unix") > 0)
258 {
259 return;
260 // shared_ptr<UnixStreamFactory> factory
261 // = static_pointer_cast<UnixStreamFactory>(m_factories["unix"]);
262 // shared_ptr<UnixStreamChannel> unixChannel = factory->findChannel(path);
263
264 // if (static_cast<bool>(unixChannel))
265 // {
266 // return;
267 // }
268 }
269
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700270 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
271 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
272
273 if (needToListen)
274 {
275 // Should acceptFailed callback be used somehow?
276 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
277 UnixStreamChannel::ConnectFailedCallback());
278 }
279
280 m_factories.insert(std::make_pair("unix", factory));
281 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600282#else
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300283 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, "
284 "cannot process \"unix\" section");
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600285#endif // HAVE_UNIX_SOCKETS
286
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700287}
288
289void
290FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
291{
292 // ; the tcp section contains settings of TCP faces and channels
293 // tcp
294 // {
295 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
296 // port 6363 ; TCP listener port number
297 // }
298
299 std::string port = "6363";
300 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600301 bool enableV4 = true;
302 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700303
304 for (ConfigSection::const_iterator i = configSection.begin();
305 i != configSection.end();
306 ++i)
307 {
308 if (i->first == "port")
309 {
310 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600311 try
312 {
313 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
314 NFD_LOG_TRACE("TCP port set to " << portNo);
315 }
316 catch (const std::bad_cast& error)
317 {
318 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600319 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600320 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700321 }
322 else if (i->first == "listen")
323 {
324 needToListen = parseYesNo(i, i->first, "tcp");
325 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600326 else if (i->first == "enable_v4")
327 {
328 enableV4 = parseYesNo(i, i->first, "tcp");
329 }
330 else if (i->first == "enable_v6")
331 {
332 enableV6 = parseYesNo(i, i->first, "tcp");
333 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700334 else
335 {
336 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
337 }
338 }
339
Steve DiBenedetto95152872014-04-11 12:40:59 -0600340 if (!enableV4 && !enableV6)
341 {
342 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
343 " Remove \"tcp\" section to disable TCP channels or"
344 " re-enable at least one channel type.");
345 }
346
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700347 if (!isDryRun)
348 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300349 if (m_factories.count("tcp") > 0)
350 {
351 return;
352 }
353
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700354 shared_ptr<TcpFactory> factory = ndn::make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600355 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700356
Steve DiBenedetto95152872014-04-11 12:40:59 -0600357 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700358 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600359 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
360 if (needToListen)
361 {
362 // Should acceptFailed callback be used somehow?
363 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
364 TcpChannel::ConnectFailedCallback());
365 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700366
Steve DiBenedetto95152872014-04-11 12:40:59 -0600367 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700368 }
369
Steve DiBenedetto95152872014-04-11 12:40:59 -0600370 if (enableV6)
371 {
372 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
373 if (needToListen)
374 {
375 // Should acceptFailed callback be used somehow?
376 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
377 TcpChannel::ConnectFailedCallback());
378 }
379
380 m_factories.insert(std::make_pair("tcp6", factory));
381 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700382 }
383}
384
385void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600386FaceManager::processSectionUdp(const ConfigSection& configSection,
387 bool isDryRun,
388 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700389{
390 // ; the udp section contains settings of UDP faces and channels
391 // udp
392 // {
393 // port 6363 ; UDP unicast port number
394 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
395 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
396
397 // ; NFD creates one UDP multicast face per NIC
398 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
399 // mcast_port 56363 ; UDP multicast port number
400 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
401 // }
402
403 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600404 bool enableV4 = true;
405 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700406 size_t timeout = 30;
407 size_t keepAliveInterval = 25;
408 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600409 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700410 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600411
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700412
413 for (ConfigSection::const_iterator i = configSection.begin();
414 i != configSection.end();
415 ++i)
416 {
417 if (i->first == "port")
418 {
419 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600420 try
421 {
422 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
423 NFD_LOG_TRACE("UDP port set to " << portNo);
424 }
425 catch (const std::bad_cast& error)
426 {
427 throw ConfigFile::Error("Invalid value for option " +
428 i->first + "\" in \"udp\" section");
429 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700430 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600431 else if (i->first == "enable_v4")
432 {
433 enableV4 = parseYesNo(i, i->first, "udp");
434 }
435 else if (i->first == "enable_v6")
436 {
437 enableV6 = parseYesNo(i, i->first, "udp");
438 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700439 else if (i->first == "idle_timeout")
440 {
441 try
442 {
443 timeout = i->second.get_value<size_t>();
444 }
445 catch (const std::exception& e)
446 {
447 throw ConfigFile::Error("Invalid value for option \"" +
448 i->first + "\" in \"udp\" section");
449 }
450 }
451 else if (i->first == "keep_alive_interval")
452 {
453 try
454 {
455 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700456
457 /// \todo Make use of keepAliveInterval
458 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700459 }
460 catch (const std::exception& e)
461 {
462 throw ConfigFile::Error("Invalid value for option \"" +
463 i->first + "\" in \"udp\" section");
464 }
465 }
466 else if (i->first == "mcast")
467 {
468 useMcast = parseYesNo(i, i->first, "udp");
469 }
470 else if (i->first == "mcast_port")
471 {
472 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600473 try
474 {
475 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
476 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
477 }
478 catch (const std::bad_cast& error)
479 {
480 throw ConfigFile::Error("Invalid value for option " +
481 i->first + "\" in \"udp\" section");
482 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700483 }
484 else if (i->first == "mcast_group")
485 {
486 using namespace boost::asio::ip;
487 mcastGroup = i->second.get_value<std::string>();
488 try
489 {
490 address mcastGroupTest = address::from_string(mcastGroup);
491 if (!mcastGroupTest.is_v4())
492 {
493 throw ConfigFile::Error("Invalid value for option \"" +
494 i->first + "\" in \"udp\" section");
495 }
496 }
497 catch(const std::runtime_error& e)
498 {
499 throw ConfigFile::Error("Invalid value for option \"" +
500 i->first + "\" in \"udp\" section");
501 }
502 }
503 else
504 {
505 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
506 }
507 }
508
Steve DiBenedetto95152872014-04-11 12:40:59 -0600509 if (!enableV4 && !enableV6)
510 {
511 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
512 " Remove \"udp\" section to disable UDP channels or"
513 " re-enable at least one channel type.");
514 }
515 else if (useMcast && !enableV4)
516 {
517 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
518 " have been disabled (conflicting configuration options set)");
519 }
520
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700521 /// \todo what is keep alive interval used for?
522
523 if (!isDryRun)
524 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300525 shared_ptr<UdpFactory> factory;
526 bool isReload = false;
527 if (m_factories.count("udp") > 0) {
528 isReload = true;
529 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
530 }
531 else {
532 factory = ndn::make_shared<UdpFactory>(port);
533 m_factories.insert(std::make_pair("udp", factory));
534 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700535
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300536 if (!isReload && enableV4)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600537 {
538 shared_ptr<UdpChannel> v4Channel =
539 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
540
541 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
542 UdpChannel::ConnectFailedCallback());
543
544 m_factories.insert(std::make_pair("udp4", factory));
545 }
546
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300547 if (!isReload && enableV6)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600548 {
549 shared_ptr<UdpChannel> v6Channel =
550 factory->createChannel("::", port, time::seconds(timeout));
551
552 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
553 UdpChannel::ConnectFailedCallback());
554 m_factories.insert(std::make_pair("udp6", factory));
555 }
556
557 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700558 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200559 std::list<shared_ptr<NetworkInterfaceInfo> > ipv4MulticastInterfaces;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600560 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
561 i != nicList.end();
562 ++i)
563 {
564 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
565 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
566 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200567 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600568 }
569 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200570
571 bool isNicNameNecessary = false;
572
573#if defined(__linux__)
574 if (ipv4MulticastInterfaces.size() > 1)
575 {
576 //On Linux, if we have more than one MulticastUdpFace we need to specify
577 //the name of the interface
578 isNicNameNecessary = true;
579 }
580#endif
581
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300582 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
583 for (UdpFactory::MulticastFaceMap::const_iterator i =
584 factory->getMulticastFaces().begin();
585 i != factory->getMulticastFaces().end();
586 ++i)
587 {
588 multicastFacesToRemove.push_back(i->second);
589 }
590
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200591 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i =
592 ipv4MulticastInterfaces.begin();
593 i != ipv4MulticastInterfaces.end();
594 ++i)
595 {
596 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
597 shared_ptr<MulticastUdpFace> newFace;
598 newFace = factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
599 mcastGroup,
600 mcastPort,
601 isNicNameNecessary ? nic->name : "");
602
603 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300604 multicastFacesToRemove.remove(newFace);
605 }
606
607 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
608 multicastFacesToRemove.begin();
609 i != multicastFacesToRemove.end();
610 ++i)
611 {
612 (*i)->close();
613 }
614 }
615 else
616 {
617 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
618 for (UdpFactory::MulticastFaceMap::const_iterator i =
619 factory->getMulticastFaces().begin();
620 i != factory->getMulticastFaces().end();
621 ++i)
622 {
623 multicastFacesToRemove.push_back(i->second);
624 }
625
626 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
627 multicastFacesToRemove.begin();
628 i != multicastFacesToRemove.end();
629 ++i)
630 {
631 (*i)->close();
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200632 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600633 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700634 }
635}
636
637void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600638FaceManager::processSectionEther(const ConfigSection& configSection,
639 bool isDryRun,
640 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700641{
642 // ; the ether section contains settings of Ethernet faces and channels
643 // ether
644 // {
645 // ; NFD creates one Ethernet multicast face per NIC
646 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
647 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
648 // }
649
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700650#if defined(HAVE_LIBPCAP)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600651
652 using ethernet::Address;
653
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700654 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600655 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700656
657 for (ConfigSection::const_iterator i = configSection.begin();
658 i != configSection.end();
659 ++i)
660 {
661 if (i->first == "mcast")
662 {
663 useMcast = parseYesNo(i, i->first, "ether");
664 }
665
666 else if (i->first == "mcast_group")
667 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600668 mcastGroup = Address::fromString(i->second.get_value<std::string>());
669 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700670 {
671 throw ConfigFile::Error("Invalid value for option \"" +
672 i->first + "\" in \"ether\" section");
673 }
674 }
675 else
676 {
677 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
678 }
679 }
680
681 if (!isDryRun)
682 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300683 shared_ptr<EthernetFactory> factory;
684 if (m_factories.count("ether") > 0) {
685 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
686 }
687 else {
688 factory = ndn::make_shared<EthernetFactory>();
689 m_factories.insert(std::make_pair("ether", factory));
690 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700691
692 if (useMcast)
693 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300694 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
695 for (EthernetFactory::MulticastFaceMap::const_iterator i =
696 factory->getMulticastFaces().begin();
697 i != factory->getMulticastFaces().end();
698 ++i)
699 {
700 multicastFacesToRemove.push_back(i->second);
701 }
702
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600703 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
704 i != nicList.end();
705 ++i)
706 {
707 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
708 if (nic->isUp() && nic->isMulticastCapable())
709 {
710 try
711 {
712 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100713 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700714
715 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300716 multicastFacesToRemove.remove(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600717 }
718 catch (const EthernetFactory::Error& factoryError)
719 {
720 NFD_LOG_ERROR(factoryError.what() << ", continuing");
721 }
722 catch (const EthernetFace::Error& faceError)
723 {
724 NFD_LOG_ERROR(faceError.what() << ", continuing");
725 }
726 }
727 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300728
729 for (std::list<shared_ptr<EthernetFace> >::iterator i =
730 multicastFacesToRemove.begin();
731 i != multicastFacesToRemove.end();
732 ++i)
733 {
734 (*i)->close();
735 }
736 }
737 else
738 {
739 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
740 for (EthernetFactory::MulticastFaceMap::const_iterator i =
741 factory->getMulticastFaces().begin();
742 i != factory->getMulticastFaces().end();
743 ++i)
744 {
745 multicastFacesToRemove.push_back(i->second);
746 }
747
748 for (std::list<shared_ptr<EthernetFace> >::iterator i =
749 multicastFacesToRemove.begin();
750 i != multicastFacesToRemove.end();
751 ++i)
752 {
753 (*i)->close();
754 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700755 }
756 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600757#else
758 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700759#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700760}
761
Wentao Shang53df1632014-04-21 12:01:32 -0700762void
763FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
764{
765 // ; the websocket section contains settings of WebSocket faces and channels
766 // websocket
767 // {
768 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
769 // port 9696 ; WebSocket listener port number
770 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
771 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
772 // }
773
774#if defined(HAVE_WEBSOCKET)
775
776 std::string port = "9696";
777 bool needToListen = true;
778 bool enableV4 = true;
779 bool enableV6 = true;
780
781 for (ConfigSection::const_iterator i = configSection.begin();
782 i != configSection.end();
783 ++i)
784 {
785 if (i->first == "port")
786 {
787 port = i->second.get_value<std::string>();
788 try
789 {
790 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
791 NFD_LOG_TRACE("WebSocket port set to " << portNo);
792 }
793 catch (const std::bad_cast& error)
794 {
795 throw ConfigFile::Error("Invalid value for option " +
796 i->first + "\" in \"websocket\" section");
797 }
798 }
799 else if (i->first == "listen")
800 {
801 needToListen = parseYesNo(i, i->first, "websocket");
802 }
803 else if (i->first == "enable_v4")
804 {
805 enableV4 = parseYesNo(i, i->first, "websocket");
806 }
807 else if (i->first == "enable_v6")
808 {
809 enableV6 = parseYesNo(i, i->first, "websocket");
810 }
811 else
812 {
813 throw ConfigFile::Error("Unrecognized option \"" +
814 i->first + "\" in \"websocket\" section");
815 }
816 }
817
818 if (!enableV4 && !enableV6)
819 {
820 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
821 " Remove \"websocket\" section to disable WebSocket channels or"
822 " re-enable at least one channel type.");
823 }
824
825 if (!enableV4 && enableV6)
826 {
827 throw ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel.");
828 }
829
830 if (!isDryRun)
831 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300832 if (m_factories.count("websocket") > 0)
833 {
834 return;
835 }
836
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700837 shared_ptr<WebSocketFactory> factory = ndn::make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700838 m_factories.insert(std::make_pair("websocket", factory));
Wentao Shang53df1632014-04-21 12:01:32 -0700839
840 if (enableV6 && enableV4)
841 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600842 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700843 if (needToListen)
844 {
845 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
846 }
847
848 m_factories.insert(std::make_pair("websocket46", factory));
849 }
850 else if (enableV4)
851 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600852 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700853 if (needToListen)
854 {
855 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
856 }
857
858 m_factories.insert(std::make_pair("websocket4", factory));
859 }
860 }
861#else
862 throw ConfigFile::Error("NFD was compiled without WebSocket, "
863 "cannot process \"websocket\" section");
864#endif // HAVE_WEBSOCKET
865}
866
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700867
868void
869FaceManager::onFaceRequest(const Interest& request)
870{
871 const Name& command = request.getName();
872 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600873 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700874
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300875 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor =
876 m_unsignedVerbDispatch.find(verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600877 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
878 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700879 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700880 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600881 }
882 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600883 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700884 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700885 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700886 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700887 }
888 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
889 !COMMAND_PREFIX.isPrefixOf(command))
890 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700891 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700892 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700893 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600894 else
895 {
896 validate(request,
897 bind(&FaceManager::onValidatedFaceRequest, this, _1),
898 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
899 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700900}
901
902void
903FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
904{
905 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600906 const Name::Component& verb = command[COMMAND_PREFIX.size()];
907 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700908
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600909 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
910 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700911 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600912 ControlParameters parameters;
913 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700914 {
915 sendResponse(command, 400, "Malformed command");
916 return;
917 }
918
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700919 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600920 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700921 }
922 else
923 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700924 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700925 sendResponse(command, 501, "Unsupported command");
926 }
927
928}
929
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700930void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700931FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
932{
933 m_faceTable.add(newFace);
934
Junxiao Shi6e694322014-04-03 10:27:13 -0700935 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700936}
937
938void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700939FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600940 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700941 const shared_ptr<Face>& newFace)
942{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700943 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600944 parameters.setFaceId(newFace->getId());
Steve DiBenedetto25999282014-05-22 15:25:12 -0600945 parameters.setUri(newFace->getRemoteUri().toString());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700946
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600947 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700948}
949
950void
951FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
952{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700953 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600954 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700955}
956
957void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600958FaceManager::createFace(const Interest& request,
959 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700960{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600961 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600962 ndn::nfd::FaceCreateCommand command;
963
964 if (!validateParameters(command, parameters))
965 {
966 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600967 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600968 return;
969 }
970
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700971 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600972 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700973 {
974 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600975 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700976 return;
977 }
978
979 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
980 if (factory == m_factories.end())
981 {
982 sendResponse(requestName, 501, "Unsupported protocol");
983 return;
984 }
985
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600986 try
987 {
988 factory->second->createFace(uri,
989 bind(&FaceManager::onCreated,
990 this, requestName, parameters, _1),
991 bind(&FaceManager::onConnectFailed,
992 this, requestName, _1));
993 }
994 catch (const std::runtime_error& error)
995 {
996 std::string errorMessage = "NFD error: ";
997 errorMessage += error.what();
998
999 NFD_LOG_ERROR(errorMessage);
1000 sendResponse(requestName, 500, errorMessage);
1001 }
1002 catch (const std::logic_error& error)
1003 {
1004 std::string errorMessage = "NFD error: ";
1005 errorMessage += error.what();
1006
1007 NFD_LOG_ERROR(errorMessage);
1008 sendResponse(requestName, 500, errorMessage);
1009 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001010}
1011
1012
1013void
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001014FaceManager::destroyFace(const Interest& request,
1015 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001016{
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001017 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001018 ndn::nfd::FaceDestroyCommand command;
1019
1020 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001021 {
1022 sendResponse(requestName, 400, "Malformed command");
1023 return;
1024 }
1025
1026 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001027 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001028 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001029 target->close();
1030 }
Steve DiBenedettoba749052014-03-22 19:54:53 -06001031
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001032 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001033
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001034}
1035
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001036void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001037FaceManager::onAddFace(shared_ptr<Face> face)
1038{
Junxiao Shi6e694322014-04-03 10:27:13 -07001039 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001040 notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
1041 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001042
Junxiao Shi6e694322014-04-03 10:27:13 -07001043 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001044}
1045
1046void
1047FaceManager::onRemoveFace(shared_ptr<Face> face)
1048{
Junxiao Shi6e694322014-04-03 10:27:13 -07001049 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001050 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
1051 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001052
Junxiao Shi6e694322014-04-03 10:27:13 -07001053 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001054}
1055
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001056bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001057FaceManager::extractLocalControlParameters(const Interest& request,
1058 ControlParameters& parameters,
1059 ControlCommand& command,
1060 shared_ptr<LocalFace>& outFace,
1061 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001062{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001063 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001064 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001065 sendResponse(request.getName(), 400, "Malformed command");
1066 return false;
1067 }
1068
1069 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
1070
1071 if (!static_cast<bool>(face))
1072 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001073 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001074 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001075 return false;
1076 }
1077 else if (!face->isLocal())
1078 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001079 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
1080 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001081 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001082 return false;
1083 }
1084
1085 outFace = dynamic_pointer_cast<LocalFace>(face);
1086 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
1087
1088 return true;
1089}
1090
1091void
1092FaceManager::enableLocalControl(const Interest& request,
1093 ControlParameters& parameters)
1094{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001095 ndn::nfd::FaceEnableLocalControlCommand command;
1096
1097
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001098 shared_ptr<LocalFace> face;
1099 LocalControlFeature feature;
1100
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001101 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001102 {
1103 face->setLocalControlHeaderFeature(feature, true);
1104 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1105 }
1106}
1107
1108void
1109FaceManager::disableLocalControl(const Interest& request,
1110 ControlParameters& parameters)
1111{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001112 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001113 shared_ptr<LocalFace> face;
1114 LocalControlFeature feature;
1115
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001116 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001117 {
1118 face->setLocalControlHeaderFeature(feature, false);
1119 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1120 }
1121}
1122
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001123void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001124FaceManager::listFaces(const Interest& request)
1125{
1126 const Name& command = request.getName();
1127 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001128
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001129 if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
1130 !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001131 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001132 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001133 sendResponse(command, 400, "Malformed command");
1134 return;
1135 }
1136
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001137 m_faceStatusPublisher.publish();
1138}
1139
1140void
1141FaceManager::listChannels(const Interest& request)
1142{
1143 NFD_LOG_DEBUG("in listChannels");
1144 const Name& command = request.getName();
1145 const size_t commandNComps = command.size();
1146
1147 if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
1148 !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
1149 {
1150 NFD_LOG_DEBUG("command result: malformed");
1151 sendResponse(command, 400, "Malformed command");
1152 return;
1153 }
1154
1155 NFD_LOG_DEBUG("publishing");
1156 m_channelStatusPublisher.publish();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001157}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001158
Chengyu Fan320d2332014-10-29 16:40:33 -06001159void
1160FaceManager::listQueriedFaces(const Interest& request)
1161{
1162 NFD_LOG_DEBUG("in listQueriedFaces");
1163 const Name& query = request.getName();
1164 const size_t queryNComps = query.size();
1165
1166 if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
1167 !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
1168 {
1169 NFD_LOG_DEBUG("query result: malformed");
1170 //sendNack(query);
1171 return;
1172 }
1173
1174 ndn::nfd::FaceQueryFilter faceFilter;
1175 try
1176 {
1177 faceFilter.wireDecode(query[-1].blockFromValue());
1178 }
1179 catch (tlv::Error&)
1180 {
1181 NFD_LOG_DEBUG("query result: malformed filter");
1182 //sendNack(query);
1183 return;
1184 }
1185
1186 FaceQueryStatusPublisher
1187 faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
1188
1189 faceQueryStatusPublisher.publish();
1190}
1191
Alexander Afanasyev5959b012014-06-02 19:18:12 +03001192shared_ptr<ProtocolFactory>
1193FaceManager::findFactory(const std::string& protocol)
1194{
1195 FactoryMap::iterator factory = m_factories.find(protocol);
1196 if (factory != m_factories.end())
1197 return factory->second;
1198 else
1199 return shared_ptr<ProtocolFactory>();
1200}
1201
1202
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001203} // namespace nfd