NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
tcp-factory.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2018, 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.
10  *
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/>.
24  */
25 
26 #include "tcp-factory.hpp"
27 
28 #include <ndn-cxx/net/address-converter.hpp>
29 
30 namespace nfd {
31 namespace face {
32 
33 namespace ip = boost::asio::ip;
34 
35 NFD_LOG_INIT("TcpFactory");
37 
38 const std::string&
40 {
41  static std::string id("tcp");
42  return id;
43 }
44 
46  : ProtocolFactory(params)
47 {
48 }
49 
50 void
53 {
54  // tcp
55  // {
56  // listen yes
57  // port 6363
58  // enable_v4 yes
59  // enable_v6 yes
60  // }
61 
62  m_wantCongestionMarking = context.generalConfig.wantCongestionMarking;
63 
64  if (!configSection) {
65  if (!context.isDryRun && !m_channels.empty()) {
66  NFD_LOG_WARN("Cannot disable tcp4 and tcp6 channels after initialization");
67  }
68  return;
69  }
70 
71  bool wantListen = true;
72  uint16_t port = 6363;
73  bool enableV4 = true;
74  bool enableV6 = true;
75  IpAddressPredicate local;
76  bool isLocalConfigured = false;
77 
78  for (const auto& pair : *configSection) {
79  const std::string& key = pair.first;
80 
81  if (key == "listen") {
82  wantListen = ConfigFile::parseYesNo(pair, "face_system.tcp");
83  }
84  else if (key == "port") {
85  port = ConfigFile::parseNumber<uint16_t>(pair, "face_system.tcp");
86  }
87  else if (key == "enable_v4") {
88  enableV4 = ConfigFile::parseYesNo(pair, "face_system.tcp");
89  }
90  else if (key == "enable_v6") {
91  enableV6 = ConfigFile::parseYesNo(pair, "face_system.tcp");
92  }
93  else if (key == "local") {
94  isLocalConfigured = true;
95  for (const auto& localPair : pair.second) {
96  const std::string& localKey = localPair.first;
97  if (localKey == "whitelist") {
98  local.parseWhitelist(localPair.second);
99  }
100  else if (localKey == "blacklist") {
101  local.parseBlacklist(localPair.second);
102  }
103  else {
104  BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.tcp.local." + localKey));
105  }
106  }
107  }
108  else {
109  BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.tcp." + key));
110  }
111  }
112  if (!isLocalConfigured) {
113  local.assign({{"subnet", "127.0.0.0/8"}, {"subnet", "::1/128"}}, {});
114  }
115 
116  if (!enableV4 && !enableV6) {
117  BOOST_THROW_EXCEPTION(ConfigFile::Error(
118  "IPv4 and IPv6 TCP channels have been disabled. Remove face_system.tcp section to disable "
119  "TCP channels or enable at least one channel type."));
120  }
121 
122  if (!context.isDryRun) {
123  providedSchemes.insert("tcp");
124 
125  if (enableV4) {
126  tcp::Endpoint endpoint(ip::tcp::v4(), port);
127  shared_ptr<TcpChannel> v4Channel = this->createChannel(endpoint);
128  if (wantListen && !v4Channel->isListening()) {
129  v4Channel->listen(this->addFace, nullptr);
130  }
131  providedSchemes.insert("tcp4");
132  }
133  else if (providedSchemes.count("tcp4") > 0) {
134  NFD_LOG_WARN("Cannot close tcp4 channel after its creation");
135  }
136 
137  if (enableV6) {
138  tcp::Endpoint endpoint(ip::tcp::v6(), port);
139  shared_ptr<TcpChannel> v6Channel = this->createChannel(endpoint);
140  if (wantListen && !v6Channel->isListening()) {
141  v6Channel->listen(this->addFace, nullptr);
142  }
143  providedSchemes.insert("tcp6");
144  }
145  else if (providedSchemes.count("tcp6") > 0) {
146  NFD_LOG_WARN("Cannot close tcp6 channel after its creation");
147  }
148 
149  m_local = std::move(local);
150  }
151 }
152 
153 void
155  const FaceCreatedCallback& onCreated,
156  const FaceCreationFailedCallback& onFailure)
157 {
158  BOOST_ASSERT(req.remoteUri.isCanonical());
159 
160  if (req.localUri) {
161  NFD_LOG_TRACE("Cannot create unicast TCP face with LocalUri");
162  onFailure(406, "Unicast TCP faces cannot be created with a LocalUri");
163  return;
164  }
165 
167  NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
168  onFailure(406, "Outgoing TCP faces do not support on-demand persistency");
169  return;
170  }
171 
173  boost::lexical_cast<uint16_t>(req.remoteUri.getPort()));
174 
175  // a canonical tcp4/tcp6 FaceUri cannot have a multicast address
176  BOOST_ASSERT(!endpoint.address().is_multicast());
177 
178  if (req.params.wantLocalFields && !endpoint.address().is_loopback()) {
179  NFD_LOG_TRACE("createFace cannot create non-local face with local fields enabled");
180  onFailure(406, "Local fields can only be enabled on faces with local scope");
181  return;
182  }
183 
184  // very simple logic for now
185  for (const auto& i : m_channels) {
186  if ((i.first.address().is_v4() && endpoint.address().is_v4()) ||
187  (i.first.address().is_v6() && endpoint.address().is_v6())) {
188  i.second->connect(endpoint, req.params, onCreated, onFailure);
189  return;
190  }
191  }
192 
193  NFD_LOG_TRACE("No channels available to connect to " << endpoint);
194  onFailure(504, "No channels available to connect");
195 }
196 
197 shared_ptr<TcpChannel>
199 {
200  auto it = m_channels.find(endpoint);
201  if (it != m_channels.end())
202  return it->second;
203 
204  auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking,
205  bind(&TcpFactory::determineFaceScopeFromAddresses, this, _1, _2));
206  m_channels[endpoint] = channel;
207  return channel;
208 }
209 
210 std::vector<shared_ptr<const Channel>>
212 {
213  return getChannelsFromMap(m_channels);
214 }
215 
217 TcpFactory::determineFaceScopeFromAddresses(const boost::asio::ip::address& localAddress,
218  const boost::asio::ip::address& remoteAddress) const
219 {
220  if (m_local(localAddress) && m_local(remoteAddress)) {
222  }
224 }
225 
226 } // namespace face
227 } // namespace nfd
std::set< std::string > providedSchemes
FaceUri schemes provided by this ProtocolFactory.
void assign(std::initializer_list< std::pair< std::string, std::string >> whitelist, std::initializer_list< std::pair< std::string, std::string >> blacklist)
const std::string & getHost() const
get host (domain)
Definition: face-uri.hpp:120
static bool parseYesNo(const ConfigSection &node, const std::string &key, const std::string &sectionName)
parse a config option that can be either "yes" or "no"
Definition: config-file.cpp:59
void parseWhitelist(const boost::property_tree::ptree &list)
static const std::string & getId()
Definition: tcp-factory.cpp:39
const std::string & getPort() const
get port
Definition: face-uri.hpp:127
NFD_REGISTER_PROTOCOL_FACTORY(EthernetFactory)
std::function< void(uint32_t status, const std::string &reason)> FaceCreationFailedCallback
Prototype for the callback that is invoked when a face fails to be created.
Definition: channel.hpp:44
boost::optional< const ConfigSection & > OptionalConfigSection
an optional config file section
Definition: config-file.hpp:41
std::function< void(const shared_ptr< Face > &face)> FaceCreatedCallback
Prototype for the callback that is invoked when a face is created (in response to an incoming connect...
Definition: channel.hpp:40
FaceCreatedCallback addFace
callback when a new face is created
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
void parseBlacklist(const boost::property_tree::ptree &list)
Provides support for an underlying protocol.
protocol factory for TCP over IPv4 and IPv6
Definition: tcp-factory.hpp:37
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
boost::asio::ip::tcp::endpoint Endpoint
Definition: tcp-channel.hpp:35
void createFace(const CreateFaceRequest &req, const FaceCreatedCallback &onCreated, const FaceCreationFailedCallback &onFailure) override
Try to create a unicast face using the supplied parameters.
TcpFactory(const CtorParams &params)
Definition: tcp-factory.cpp:45
Parameters to ProtocolFactory constructor.
ndn::nfd::FacePersistency persistency
Definition: channel.hpp:100
context for processing a config section in ProtocolFactory
Definition: face-system.hpp:92
boost::asio::ip::address addressFromString(const std::string &address, boost::system::error_code &ec)
parse and convert the input string into an IP address
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
std::vector< shared_ptr< const Channel > > getChannels() const override
Encapsulates a face creation request and all its parameters.
static std::vector< shared_ptr< const Channel > > getChannelsFromMap(const ChannelMap &channelMap)
Represents a predicate to accept or reject an IP address.
void processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext &context) override
process face_system.tcp config section
Definition: tcp-factory.cpp:51
bool isCanonical() const
determine whether this FaceUri is in canonical form
Definition: face-uri.cpp:637
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
shared_ptr< TcpChannel > createChannel(const tcp::Endpoint &localEndpoint)
Create TCP-based channel using tcp::Endpoint.