blob: 64d7af4f42e0679cb12ad6345f86b46b1869ca95 [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 DiBenedettoabe9e972014-02-20 15:37:04 -070029#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060030#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070031#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070032#include "face/tcp-factory.hpp"
33#include "face/udp-factory.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070034#include "core/config-file.hpp"
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060035
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060036#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060038#endif // HAVE_UNIX_SOCKETS
39
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070040#ifdef HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041#include "face/ethernet-factory.hpp"
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070042#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043
Wentao Shang53df1632014-04-21 12:01:32 -070044#ifdef HAVE_WEBSOCKET
45#include "face/websocket-factory.hpp"
46#endif // HAVE_WEBSOCKET
47
Alexander Afanasyev4a771362014-04-24 21:29:33 -070048#include <ndn-cxx/management/nfd-face-event-notification.hpp>
Chengyu Fan320d2332014-10-29 16:40:33 -060049#include <ndn-cxx/management/nfd-face-query-filter.hpp>
Davide Pesavento52a18f92014-04-10 00:55:01 +020050
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070051namespace nfd {
52
53NFD_LOG_INIT("FaceManager");
54
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060055const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070056
57const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
58 FaceManager::COMMAND_PREFIX.size() +
59 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060060 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070061
62const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
63 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070064 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070065
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060066const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070067 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060068 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060069 Name::Component("create"),
70 &FaceManager::createFace
71 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070072
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060073 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060074 Name::Component("destroy"),
75 &FaceManager::destroyFace
76 ),
77
78 SignedVerbAndProcessor(
79 Name::Component("enable-local-control"),
80 &FaceManager::enableLocalControl
81 ),
82
83 SignedVerbAndProcessor(
84 Name::Component("disable-local-control"),
85 &FaceManager::disableLocalControl
86 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070087 };
88
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060089const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
90 {
91 UnsignedVerbAndProcessor(
92 Name::Component("list"),
93 &FaceManager::listFaces
94 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060095
96 UnsignedVerbAndProcessor(
97 Name::Component("events"),
98 &FaceManager::ignoreUnsignedVerb
99 ),
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600100
101 UnsignedVerbAndProcessor(
102 Name::Component("channels"),
103 &FaceManager::listChannels
104 ),
Chengyu Fan320d2332014-10-29 16:40:33 -0600105
106 UnsignedVerbAndProcessor(
107 Name::Component("query"),
108 &FaceManager::listQueriedFaces
109 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600110 };
111
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600112const Name FaceManager::FACES_LIST_DATASET_PREFIX("/localhost/nfd/faces/list");
113const size_t FaceManager::FACES_LIST_DATASET_NCOMPS = FACES_LIST_DATASET_PREFIX.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600114
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600115const Name FaceManager::FACE_EVENTS_PREFIX("/localhost/nfd/faces/events");
116
117const Name FaceManager::CHANNELS_LIST_DATASET_PREFIX("/localhost/nfd/faces/channels");
118const size_t FaceManager::CHANNELS_LIST_DATASET_NCOMPS = CHANNELS_LIST_DATASET_PREFIX.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700119
Chengyu Fan320d2332014-10-29 16:40:33 -0600120const Name FaceManager::FACES_QUERY_DATASET_PREFIX("/localhost/nfd/faces/query");
121const size_t FaceManager::FACES_QUERY_DATASET_NCOMPS = FACES_QUERY_DATASET_PREFIX.size() + 1;
122
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700123FaceManager::FaceManager(FaceTable& faceTable,
Vince Lehman5144f822014-07-23 15:12:56 -0700124 shared_ptr<InternalFace> face,
125 ndn::KeyChain& keyChain)
126 : ManagerBase(face, FACE_MANAGER_PRIVILEGE, keyChain)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700127 , m_faceTable(faceTable)
Vince Lehman5144f822014-07-23 15:12:56 -0700128 , m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
129 , m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
Junxiao Shi15b12e72014-08-09 19:56:24 -0700130 , m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600131 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600132 SIGNED_COMMAND_VERBS +
133 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600134 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600135 UNSIGNED_COMMAND_VERBS +
136 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600137
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700138{
139 face->setInterestFilter("/localhost/nfd/faces",
140 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600141
142 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
143 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700144}
145
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600146FaceManager::~FaceManager()
147{
148
149}
150
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700151void
152FaceManager::setConfigFile(ConfigFile& configFile)
153{
154 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600155 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700156}
157
158
159void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600160FaceManager::onConfig(const ConfigSection& configSection,
161 bool isDryRun,
162 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700163{
164 bool hasSeenUnix = false;
165 bool hasSeenTcp = false;
166 bool hasSeenUdp = false;
167 bool hasSeenEther = false;
Wentao Shang53df1632014-04-21 12:01:32 -0700168 bool hasSeenWebSocket = false;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700169
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600170 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
171
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700172 for (ConfigSection::const_iterator item = configSection.begin();
173 item != configSection.end();
174 ++item)
175 {
176 if (item->first == "unix")
177 {
178 if (hasSeenUnix)
179 throw Error("Duplicate \"unix\" section");
180 hasSeenUnix = true;
181
182 processSectionUnix(item->second, isDryRun);
183 }
184 else if (item->first == "tcp")
185 {
186 if (hasSeenTcp)
187 throw Error("Duplicate \"tcp\" section");
188 hasSeenTcp = true;
189
190 processSectionTcp(item->second, isDryRun);
191 }
192 else if (item->first == "udp")
193 {
194 if (hasSeenUdp)
195 throw Error("Duplicate \"udp\" section");
196 hasSeenUdp = true;
197
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600198 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700199 }
200 else if (item->first == "ether")
201 {
202 if (hasSeenEther)
203 throw Error("Duplicate \"ether\" section");
204 hasSeenEther = true;
205
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600206 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700207 }
Wentao Shang53df1632014-04-21 12:01:32 -0700208 else if (item->first == "websocket")
209 {
210 if (hasSeenWebSocket)
211 throw Error("Duplicate \"websocket\" section");
212 hasSeenWebSocket = true;
213
214 processSectionWebSocket(item->second, isDryRun);
215 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700216 else
217 {
218 throw Error("Unrecognized option \"" + item->first + "\"");
219 }
220 }
221}
222
223void
224FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
225{
226 // ; the unix section contains settings of UNIX stream faces and channels
227 // unix
228 // {
229 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
230 // path /var/run/nfd.sock ; UNIX stream listener path
231 // }
232
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600233#if defined(HAVE_UNIX_SOCKETS)
234
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700235 bool needToListen = true;
236 std::string path = "/var/run/nfd.sock";
237
238 for (ConfigSection::const_iterator i = configSection.begin();
239 i != configSection.end();
240 ++i)
241 {
242 if (i->first == "path")
243 {
244 path = i->second.get_value<std::string>();
245 }
246 else if (i->first == "listen")
247 {
248 needToListen = parseYesNo(i, i->first, "unix");
249 }
250 else
251 {
252 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
253 }
254 }
255
256 if (!isDryRun)
257 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300258 if (m_factories.count("unix") > 0)
259 {
260 return;
261 // shared_ptr<UnixStreamFactory> factory
262 // = static_pointer_cast<UnixStreamFactory>(m_factories["unix"]);
263 // shared_ptr<UnixStreamChannel> unixChannel = factory->findChannel(path);
264
265 // if (static_cast<bool>(unixChannel))
266 // {
267 // return;
268 // }
269 }
270
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700271 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
272 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
273
274 if (needToListen)
275 {
276 // Should acceptFailed callback be used somehow?
277 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
278 UnixStreamChannel::ConnectFailedCallback());
279 }
280
281 m_factories.insert(std::make_pair("unix", factory));
282 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600283#else
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300284 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, "
285 "cannot process \"unix\" section");
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600286#endif // HAVE_UNIX_SOCKETS
287
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700288}
289
290void
291FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
292{
293 // ; the tcp section contains settings of TCP faces and channels
294 // tcp
295 // {
296 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
297 // port 6363 ; TCP listener port number
298 // }
299
300 std::string port = "6363";
301 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600302 bool enableV4 = true;
303 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700304
305 for (ConfigSection::const_iterator i = configSection.begin();
306 i != configSection.end();
307 ++i)
308 {
309 if (i->first == "port")
310 {
311 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600312 try
313 {
314 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
315 NFD_LOG_TRACE("TCP port set to " << portNo);
316 }
317 catch (const std::bad_cast& error)
318 {
319 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600320 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600321 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700322 }
323 else if (i->first == "listen")
324 {
325 needToListen = parseYesNo(i, i->first, "tcp");
326 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600327 else if (i->first == "enable_v4")
328 {
329 enableV4 = parseYesNo(i, i->first, "tcp");
330 }
331 else if (i->first == "enable_v6")
332 {
333 enableV6 = parseYesNo(i, i->first, "tcp");
334 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700335 else
336 {
337 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
338 }
339 }
340
Steve DiBenedetto95152872014-04-11 12:40:59 -0600341 if (!enableV4 && !enableV6)
342 {
343 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
344 " Remove \"tcp\" section to disable TCP channels or"
345 " re-enable at least one channel type.");
346 }
347
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700348 if (!isDryRun)
349 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300350 if (m_factories.count("tcp") > 0)
351 {
352 return;
353 }
354
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700355 shared_ptr<TcpFactory> factory = ndn::make_shared<TcpFactory>(port);
Steve DiBenedetto95152872014-04-11 12:40:59 -0600356 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700357
Steve DiBenedetto95152872014-04-11 12:40:59 -0600358 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700359 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600360 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
361 if (needToListen)
362 {
363 // Should acceptFailed callback be used somehow?
364 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
365 TcpChannel::ConnectFailedCallback());
366 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700367
Steve DiBenedetto95152872014-04-11 12:40:59 -0600368 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700369 }
370
Steve DiBenedetto95152872014-04-11 12:40:59 -0600371 if (enableV6)
372 {
373 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
374 if (needToListen)
375 {
376 // Should acceptFailed callback be used somehow?
377 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
378 TcpChannel::ConnectFailedCallback());
379 }
380
381 m_factories.insert(std::make_pair("tcp6", factory));
382 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700383 }
384}
385
386void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600387FaceManager::processSectionUdp(const ConfigSection& configSection,
388 bool isDryRun,
389 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700390{
391 // ; the udp section contains settings of UDP faces and channels
392 // udp
393 // {
394 // port 6363 ; UDP unicast port number
395 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
396 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
397
398 // ; NFD creates one UDP multicast face per NIC
399 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
400 // mcast_port 56363 ; UDP multicast port number
401 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
402 // }
403
404 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600405 bool enableV4 = true;
406 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700407 size_t timeout = 30;
408 size_t keepAliveInterval = 25;
409 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600410 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700411 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600412
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700413
414 for (ConfigSection::const_iterator i = configSection.begin();
415 i != configSection.end();
416 ++i)
417 {
418 if (i->first == "port")
419 {
420 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600421 try
422 {
423 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
424 NFD_LOG_TRACE("UDP port set to " << portNo);
425 }
426 catch (const std::bad_cast& error)
427 {
428 throw ConfigFile::Error("Invalid value for option " +
429 i->first + "\" in \"udp\" section");
430 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700431 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600432 else if (i->first == "enable_v4")
433 {
434 enableV4 = parseYesNo(i, i->first, "udp");
435 }
436 else if (i->first == "enable_v6")
437 {
438 enableV6 = parseYesNo(i, i->first, "udp");
439 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700440 else if (i->first == "idle_timeout")
441 {
442 try
443 {
444 timeout = i->second.get_value<size_t>();
445 }
446 catch (const std::exception& e)
447 {
448 throw ConfigFile::Error("Invalid value for option \"" +
449 i->first + "\" in \"udp\" section");
450 }
451 }
452 else if (i->first == "keep_alive_interval")
453 {
454 try
455 {
456 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700457
458 /// \todo Make use of keepAliveInterval
459 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700460 }
461 catch (const std::exception& e)
462 {
463 throw ConfigFile::Error("Invalid value for option \"" +
464 i->first + "\" in \"udp\" section");
465 }
466 }
467 else if (i->first == "mcast")
468 {
469 useMcast = parseYesNo(i, i->first, "udp");
470 }
471 else if (i->first == "mcast_port")
472 {
473 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600474 try
475 {
476 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
477 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
478 }
479 catch (const std::bad_cast& error)
480 {
481 throw ConfigFile::Error("Invalid value for option " +
482 i->first + "\" in \"udp\" section");
483 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700484 }
485 else if (i->first == "mcast_group")
486 {
487 using namespace boost::asio::ip;
488 mcastGroup = i->second.get_value<std::string>();
489 try
490 {
491 address mcastGroupTest = address::from_string(mcastGroup);
492 if (!mcastGroupTest.is_v4())
493 {
494 throw ConfigFile::Error("Invalid value for option \"" +
495 i->first + "\" in \"udp\" section");
496 }
497 }
498 catch(const std::runtime_error& e)
499 {
500 throw ConfigFile::Error("Invalid value for option \"" +
501 i->first + "\" in \"udp\" section");
502 }
503 }
504 else
505 {
506 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
507 }
508 }
509
Steve DiBenedetto95152872014-04-11 12:40:59 -0600510 if (!enableV4 && !enableV6)
511 {
512 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
513 " Remove \"udp\" section to disable UDP channels or"
514 " re-enable at least one channel type.");
515 }
516 else if (useMcast && !enableV4)
517 {
518 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
519 " have been disabled (conflicting configuration options set)");
520 }
521
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700522 /// \todo what is keep alive interval used for?
523
524 if (!isDryRun)
525 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300526 shared_ptr<UdpFactory> factory;
527 bool isReload = false;
528 if (m_factories.count("udp") > 0) {
529 isReload = true;
530 factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
531 }
532 else {
533 factory = ndn::make_shared<UdpFactory>(port);
534 m_factories.insert(std::make_pair("udp", factory));
535 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700536
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300537 if (!isReload && enableV4)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600538 {
539 shared_ptr<UdpChannel> v4Channel =
540 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
541
542 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
543 UdpChannel::ConnectFailedCallback());
544
545 m_factories.insert(std::make_pair("udp4", factory));
546 }
547
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300548 if (!isReload && enableV6)
Steve DiBenedetto95152872014-04-11 12:40:59 -0600549 {
550 shared_ptr<UdpChannel> v6Channel =
551 factory->createChannel("::", port, time::seconds(timeout));
552
553 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
554 UdpChannel::ConnectFailedCallback());
555 m_factories.insert(std::make_pair("udp6", factory));
556 }
557
558 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700559 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200560 std::list<shared_ptr<NetworkInterfaceInfo> > ipv4MulticastInterfaces;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600561 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
562 i != nicList.end();
563 ++i)
564 {
565 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
566 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
567 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200568 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600569 }
570 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200571
572 bool isNicNameNecessary = false;
573
574#if defined(__linux__)
575 if (ipv4MulticastInterfaces.size() > 1)
576 {
577 //On Linux, if we have more than one MulticastUdpFace we need to specify
578 //the name of the interface
579 isNicNameNecessary = true;
580 }
581#endif
582
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300583 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
584 for (UdpFactory::MulticastFaceMap::const_iterator i =
585 factory->getMulticastFaces().begin();
586 i != factory->getMulticastFaces().end();
587 ++i)
588 {
589 multicastFacesToRemove.push_back(i->second);
590 }
591
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200592 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i =
593 ipv4MulticastInterfaces.begin();
594 i != ipv4MulticastInterfaces.end();
595 ++i)
596 {
597 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
598 shared_ptr<MulticastUdpFace> newFace;
599 newFace = factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
600 mcastGroup,
601 mcastPort,
602 isNicNameNecessary ? nic->name : "");
603
604 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300605 multicastFacesToRemove.remove(newFace);
606 }
607
608 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
609 multicastFacesToRemove.begin();
610 i != multicastFacesToRemove.end();
611 ++i)
612 {
613 (*i)->close();
614 }
615 }
616 else
617 {
618 std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
619 for (UdpFactory::MulticastFaceMap::const_iterator i =
620 factory->getMulticastFaces().begin();
621 i != factory->getMulticastFaces().end();
622 ++i)
623 {
624 multicastFacesToRemove.push_back(i->second);
625 }
626
627 for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
628 multicastFacesToRemove.begin();
629 i != multicastFacesToRemove.end();
630 ++i)
631 {
632 (*i)->close();
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200633 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600634 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700635 }
636}
637
638void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600639FaceManager::processSectionEther(const ConfigSection& configSection,
640 bool isDryRun,
641 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700642{
643 // ; the ether section contains settings of Ethernet faces and channels
644 // ether
645 // {
646 // ; NFD creates one Ethernet multicast face per NIC
647 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
648 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
649 // }
650
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700651#if defined(HAVE_LIBPCAP)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600652
653 using ethernet::Address;
654
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700655 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600656 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700657
658 for (ConfigSection::const_iterator i = configSection.begin();
659 i != configSection.end();
660 ++i)
661 {
662 if (i->first == "mcast")
663 {
664 useMcast = parseYesNo(i, i->first, "ether");
665 }
666
667 else if (i->first == "mcast_group")
668 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600669 mcastGroup = Address::fromString(i->second.get_value<std::string>());
670 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700671 {
672 throw ConfigFile::Error("Invalid value for option \"" +
673 i->first + "\" in \"ether\" section");
674 }
675 }
676 else
677 {
678 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
679 }
680 }
681
682 if (!isDryRun)
683 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300684 shared_ptr<EthernetFactory> factory;
685 if (m_factories.count("ether") > 0) {
686 factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
687 }
688 else {
689 factory = ndn::make_shared<EthernetFactory>();
690 m_factories.insert(std::make_pair("ether", factory));
691 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700692
693 if (useMcast)
694 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300695 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
696 for (EthernetFactory::MulticastFaceMap::const_iterator i =
697 factory->getMulticastFaces().begin();
698 i != factory->getMulticastFaces().end();
699 ++i)
700 {
701 multicastFacesToRemove.push_back(i->second);
702 }
703
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600704 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
705 i != nicList.end();
706 ++i)
707 {
708 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
709 if (nic->isUp() && nic->isMulticastCapable())
710 {
711 try
712 {
713 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100714 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700715
716 addCreatedFaceToForwarder(newFace);
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300717 multicastFacesToRemove.remove(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600718 }
719 catch (const EthernetFactory::Error& factoryError)
720 {
721 NFD_LOG_ERROR(factoryError.what() << ", continuing");
722 }
723 catch (const EthernetFace::Error& faceError)
724 {
725 NFD_LOG_ERROR(faceError.what() << ", continuing");
726 }
727 }
728 }
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300729
730 for (std::list<shared_ptr<EthernetFace> >::iterator i =
731 multicastFacesToRemove.begin();
732 i != multicastFacesToRemove.end();
733 ++i)
734 {
735 (*i)->close();
736 }
737 }
738 else
739 {
740 std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
741 for (EthernetFactory::MulticastFaceMap::const_iterator i =
742 factory->getMulticastFaces().begin();
743 i != factory->getMulticastFaces().end();
744 ++i)
745 {
746 multicastFacesToRemove.push_back(i->second);
747 }
748
749 for (std::list<shared_ptr<EthernetFace> >::iterator i =
750 multicastFacesToRemove.begin();
751 i != multicastFacesToRemove.end();
752 ++i)
753 {
754 (*i)->close();
755 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700756 }
757 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600758#else
759 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700760#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700761}
762
Wentao Shang53df1632014-04-21 12:01:32 -0700763void
764FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
765{
766 // ; the websocket section contains settings of WebSocket faces and channels
767 // websocket
768 // {
769 // listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
770 // port 9696 ; WebSocket listener port number
771 // enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
772 // enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
773 // }
774
775#if defined(HAVE_WEBSOCKET)
776
777 std::string port = "9696";
778 bool needToListen = true;
779 bool enableV4 = true;
780 bool enableV6 = true;
781
782 for (ConfigSection::const_iterator i = configSection.begin();
783 i != configSection.end();
784 ++i)
785 {
786 if (i->first == "port")
787 {
788 port = i->second.get_value<std::string>();
789 try
790 {
791 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
792 NFD_LOG_TRACE("WebSocket port set to " << portNo);
793 }
794 catch (const std::bad_cast& error)
795 {
796 throw ConfigFile::Error("Invalid value for option " +
797 i->first + "\" in \"websocket\" section");
798 }
799 }
800 else if (i->first == "listen")
801 {
802 needToListen = parseYesNo(i, i->first, "websocket");
803 }
804 else if (i->first == "enable_v4")
805 {
806 enableV4 = parseYesNo(i, i->first, "websocket");
807 }
808 else if (i->first == "enable_v6")
809 {
810 enableV6 = parseYesNo(i, i->first, "websocket");
811 }
812 else
813 {
814 throw ConfigFile::Error("Unrecognized option \"" +
815 i->first + "\" in \"websocket\" section");
816 }
817 }
818
819 if (!enableV4 && !enableV6)
820 {
821 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
822 " Remove \"websocket\" section to disable WebSocket channels or"
823 " re-enable at least one channel type.");
824 }
825
826 if (!enableV4 && enableV6)
827 {
828 throw ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel.");
829 }
830
831 if (!isDryRun)
832 {
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300833 if (m_factories.count("websocket") > 0)
834 {
835 return;
836 }
837
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700838 shared_ptr<WebSocketFactory> factory = ndn::make_shared<WebSocketFactory>(port);
Wentao Shang53df1632014-04-21 12:01:32 -0700839 m_factories.insert(std::make_pair("websocket", factory));
Wentao Shang53df1632014-04-21 12:01:32 -0700840
841 if (enableV6 && enableV4)
842 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600843 shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700844 if (needToListen)
845 {
846 ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
847 }
848
849 m_factories.insert(std::make_pair("websocket46", factory));
850 }
851 else if (enableV4)
852 {
Steve DiBenedettoef04f272014-06-04 14:28:31 -0600853 shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
Wentao Shang53df1632014-04-21 12:01:32 -0700854 if (needToListen)
855 {
856 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
857 }
858
859 m_factories.insert(std::make_pair("websocket4", factory));
860 }
861 }
862#else
863 throw ConfigFile::Error("NFD was compiled without WebSocket, "
864 "cannot process \"websocket\" section");
865#endif // HAVE_WEBSOCKET
866}
867
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700868
869void
870FaceManager::onFaceRequest(const Interest& request)
871{
872 const Name& command = request.getName();
873 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600874 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700875
Alexander Afanasyev5959b012014-06-02 19:18:12 +0300876 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor =
877 m_unsignedVerbDispatch.find(verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600878 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
879 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700880 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700881 (unsignedVerbProcessor->second)(this, request);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600882 }
883 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600884 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700885 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700886 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700887 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700888 }
889 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
890 !COMMAND_PREFIX.isPrefixOf(command))
891 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700892 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700893 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700894 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600895 else
896 {
897 validate(request,
898 bind(&FaceManager::onValidatedFaceRequest, this, _1),
899 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
900 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700901}
902
903void
904FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
905{
906 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600907 const Name::Component& verb = command[COMMAND_PREFIX.size()];
908 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700909
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600910 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
911 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700912 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600913 ControlParameters parameters;
914 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700915 {
916 sendResponse(command, 400, "Malformed command");
917 return;
918 }
919
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700920 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600921 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700922 }
923 else
924 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700925 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700926 sendResponse(command, 501, "Unsupported command");
927 }
928
929}
930
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700931void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700932FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
933{
934 m_faceTable.add(newFace);
935
Junxiao Shi6e694322014-04-03 10:27:13 -0700936 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700937}
938
939void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700940FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600941 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700942 const shared_ptr<Face>& newFace)
943{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700944 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600945 parameters.setFaceId(newFace->getId());
Steve DiBenedetto25999282014-05-22 15:25:12 -0600946 parameters.setUri(newFace->getRemoteUri().toString());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700947
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600948 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700949}
950
951void
952FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
953{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700954 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600955 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700956}
957
958void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600959FaceManager::createFace(const Interest& request,
960 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700961{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600962 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600963 ndn::nfd::FaceCreateCommand command;
964
965 if (!validateParameters(command, parameters))
966 {
967 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600968 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600969 return;
970 }
971
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700972 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600973 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700974 {
975 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600976 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700977 return;
978 }
979
980 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
981 if (factory == m_factories.end())
982 {
983 sendResponse(requestName, 501, "Unsupported protocol");
984 return;
985 }
986
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600987 try
988 {
989 factory->second->createFace(uri,
990 bind(&FaceManager::onCreated,
991 this, requestName, parameters, _1),
992 bind(&FaceManager::onConnectFailed,
993 this, requestName, _1));
994 }
995 catch (const std::runtime_error& error)
996 {
997 std::string errorMessage = "NFD error: ";
998 errorMessage += error.what();
999
1000 NFD_LOG_ERROR(errorMessage);
1001 sendResponse(requestName, 500, errorMessage);
1002 }
1003 catch (const std::logic_error& error)
1004 {
1005 std::string errorMessage = "NFD error: ";
1006 errorMessage += error.what();
1007
1008 NFD_LOG_ERROR(errorMessage);
1009 sendResponse(requestName, 500, errorMessage);
1010 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001011}
1012
1013
1014void
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001015FaceManager::destroyFace(const Interest& request,
1016 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001017{
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001018 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001019 ndn::nfd::FaceDestroyCommand command;
1020
1021 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001022 {
1023 sendResponse(requestName, 400, "Malformed command");
1024 return;
1025 }
1026
1027 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001028 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001029 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001030 target->close();
1031 }
Steve DiBenedettoba749052014-03-22 19:54:53 -06001032
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001033 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001034
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001035}
1036
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001037void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001038FaceManager::onAddFace(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_CREATED);
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
1047void
1048FaceManager::onRemoveFace(shared_ptr<Face> face)
1049{
Junxiao Shi6e694322014-04-03 10:27:13 -07001050 ndn::nfd::FaceEventNotification notification;
Chengyu Fanf9c2bb12014-10-06 11:52:44 -06001051 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
1052 face->copyStatusTo(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001053
Junxiao Shi6e694322014-04-03 10:27:13 -07001054 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001055}
1056
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001057bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001058FaceManager::extractLocalControlParameters(const Interest& request,
1059 ControlParameters& parameters,
1060 ControlCommand& command,
1061 shared_ptr<LocalFace>& outFace,
1062 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001063{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001064 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001065 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001066 sendResponse(request.getName(), 400, "Malformed command");
1067 return false;
1068 }
1069
1070 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
1071
1072 if (!static_cast<bool>(face))
1073 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001074 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001075 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001076 return false;
1077 }
1078 else if (!face->isLocal())
1079 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001080 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
1081 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001082 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001083 return false;
1084 }
1085
1086 outFace = dynamic_pointer_cast<LocalFace>(face);
1087 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
1088
1089 return true;
1090}
1091
1092void
1093FaceManager::enableLocalControl(const Interest& request,
1094 ControlParameters& parameters)
1095{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001096 ndn::nfd::FaceEnableLocalControlCommand command;
1097
1098
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001099 shared_ptr<LocalFace> face;
1100 LocalControlFeature feature;
1101
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001102 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001103 {
1104 face->setLocalControlHeaderFeature(feature, true);
1105 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1106 }
1107}
1108
1109void
1110FaceManager::disableLocalControl(const Interest& request,
1111 ControlParameters& parameters)
1112{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001113 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001114 shared_ptr<LocalFace> face;
1115 LocalControlFeature feature;
1116
Steve DiBenedetto51d242a2014-03-31 13:46:43 -06001117 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -06001118 {
1119 face->setLocalControlHeaderFeature(feature, false);
1120 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
1121 }
1122}
1123
Steve DiBenedettofbb40a82014-03-11 19:40:15 -06001124void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001125FaceManager::listFaces(const Interest& request)
1126{
1127 const Name& command = request.getName();
1128 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001129
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001130 if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
1131 !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001132 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -07001133 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001134 sendResponse(command, 400, "Malformed command");
1135 return;
1136 }
1137
Steve DiBenedettoef04f272014-06-04 14:28:31 -06001138 m_faceStatusPublisher.publish();
1139}
1140
1141void
1142FaceManager::listChannels(const Interest& request)
1143{
1144 NFD_LOG_DEBUG("in listChannels");
1145 const Name& command = request.getName();
1146 const size_t commandNComps = command.size();
1147
1148 if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
1149 !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
1150 {
1151 NFD_LOG_DEBUG("command result: malformed");
1152 sendResponse(command, 400, "Malformed command");
1153 return;
1154 }
1155
1156 NFD_LOG_DEBUG("publishing");
1157 m_channelStatusPublisher.publish();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -06001158}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001159
Chengyu Fan320d2332014-10-29 16:40:33 -06001160void
1161FaceManager::listQueriedFaces(const Interest& request)
1162{
1163 NFD_LOG_DEBUG("in listQueriedFaces");
1164 const Name& query = request.getName();
1165 const size_t queryNComps = query.size();
1166
1167 if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
1168 !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
1169 {
1170 NFD_LOG_DEBUG("query result: malformed");
1171 //sendNack(query);
1172 return;
1173 }
1174
1175 ndn::nfd::FaceQueryFilter faceFilter;
1176 try
1177 {
1178 faceFilter.wireDecode(query[-1].blockFromValue());
1179 }
1180 catch (tlv::Error&)
1181 {
1182 NFD_LOG_DEBUG("query result: malformed filter");
1183 //sendNack(query);
1184 return;
1185 }
1186
1187 FaceQueryStatusPublisher
1188 faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
1189
1190 faceQueryStatusPublisher.publish();
1191}
1192
Alexander Afanasyev5959b012014-06-02 19:18:12 +03001193shared_ptr<ProtocolFactory>
1194FaceManager::findFactory(const std::string& protocol)
1195{
1196 FactoryMap::iterator factory = m_factories.find(protocol);
1197 if (factory != m_factories.end())
1198 return factory->second;
1199 else
1200 return shared_ptr<ProtocolFactory>();
1201}
1202
1203
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001204} // namespace nfd