blob: cd3119e08f381f954a14493ea69f1cebc81f6d20 [file] [log] [blame]
Alexander Afanasyeva9034b02014-01-26 18:32:02 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
Alexander Afanasyev0eb70652014-02-27 18:35:07 -08007#include "tcp-factory.hpp"
Alexander Afanasyevd6655302014-02-28 08:41:28 -08008#include "core/resolver.hpp"
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -08009#include "core/logger.hpp"
Steve DiBenedettoca53ac62014-03-27 19:58:40 -060010#include "core/network-interface.hpp"
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -080011
12NFD_LOG_INIT("TcpFactory");
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080013
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080014namespace nfd {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080015
Alexander Afanasyevd6655302014-02-28 08:41:28 -080016TcpFactory::TcpFactory(const std::string& defaultPort/* = "6363"*/)
17 : m_defaultPort(defaultPort)
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080018{
Steve DiBenedettoca53ac62014-03-27 19:58:40 -060019
20}
21
22void
23TcpFactory::prohibitEndpoint(const tcp::Endpoint& endpoint)
24{
25 using namespace boost::asio::ip;
26
27 static const address_v4 ALL_V4_ENDPOINT(address_v4::from_string("0.0.0.0"));
28 static const address_v6 ALL_V6_ENDPOINT(address_v6::from_string("::"));
29
30 const address& address = endpoint.address();
31
32 if (address.is_v4() && address == ALL_V4_ENDPOINT)
33 {
34 prohibitAllIpv4Endpoints(endpoint.port());
35 }
36 else if (endpoint.address().is_v6() && address == ALL_V6_ENDPOINT)
37 {
38 prohibitAllIpv6Endpoints(endpoint.port());
39 }
40
41 NFD_LOG_TRACE("prohibiting TCP " <<
42 endpoint.address().to_string() << ":" << endpoint.port());
43
44 m_prohibitedEndpoints.insert(endpoint);
45}
46
47void
48TcpFactory::prohibitAllIpv4Endpoints(const uint16_t port)
49{
50 using namespace boost::asio::ip;
51
52 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
53
54 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
55 i != nicList.end();
56 ++i)
57 {
58 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
59 const std::vector<address_v4>& ipv4Addresses = nic->ipv4Addresses;
60
61 for (std::vector<address_v4>::const_iterator j = ipv4Addresses.begin();
62 j != ipv4Addresses.end();
63 ++j)
64 {
65 prohibitEndpoint(tcp::Endpoint(*j, port));
66 }
67 }
68}
69
70void
71TcpFactory::prohibitAllIpv6Endpoints(const uint16_t port)
72{
73 using namespace boost::asio::ip;
74
75 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
76
77 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
78 i != nicList.end();
79 ++i)
80 {
81 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
82 const std::vector<address_v6>& ipv6Addresses = nic->ipv6Addresses;
83
84 for (std::vector<address_v6>::const_iterator j = ipv6Addresses.begin();
85 j != ipv6Addresses.end();
86 ++j)
87 {
88 prohibitEndpoint(tcp::Endpoint(*j, port));
89 }
90 }
Alexander Afanasyevd6655302014-02-28 08:41:28 -080091}
92
93shared_ptr<TcpChannel>
94TcpFactory::createChannel(const tcp::Endpoint& endpoint)
95{
96 shared_ptr<TcpChannel> channel = findChannel(endpoint);
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080097 if(static_cast<bool>(channel))
98 return channel;
99
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700100 channel = make_shared<TcpChannel>(boost::cref(endpoint));
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -0800101 m_channels[endpoint] = channel;
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600102 prohibitEndpoint(endpoint);
103
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800104 NFD_LOG_DEBUG("Channel [" << endpoint << "] created");
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -0800105 return channel;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800106}
107
108shared_ptr<TcpChannel>
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800109TcpFactory::createChannel(const std::string& localHost, const std::string& localPort)
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800110{
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800111 return createChannel(TcpResolver::syncResolve(localHost, localPort));
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800112}
113
114shared_ptr<TcpChannel>
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800115TcpFactory::findChannel(const tcp::Endpoint& localEndpoint)
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800116{
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -0800117 ChannelMap::iterator i = m_channels.find(localEndpoint);
118 if (i != m_channels.end())
119 return i->second;
120 else
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800121 return shared_ptr<TcpChannel>();
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800122}
123
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800124void
125TcpFactory::createFace(const FaceUri& uri,
126 const FaceCreatedCallback& onCreated,
127 const FaceConnectFailedCallback& onConnectFailed)
128{
129 resolver::AddressSelector addressSelector = resolver::AnyAddress();
130 if (uri.getScheme() == "tcp4")
131 addressSelector = resolver::Ipv4Address();
132 else if (uri.getScheme() == "tcp6")
133 addressSelector = resolver::Ipv6Address();
134
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600135 if (!uri.getPath().empty())
136 {
137 onConnectFailed("Invalid URI");
138 }
139
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700140 TcpResolver::asyncResolve(uri.getHost(),
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800141 uri.getPort().empty() ? m_defaultPort : uri.getPort(),
142 bind(&TcpFactory::continueCreateFaceAfterResolve, this, _1,
143 onCreated, onConnectFailed),
144 onConnectFailed,
145 addressSelector);
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800146}
147
148void
149TcpFactory::continueCreateFaceAfterResolve(const tcp::Endpoint& endpoint,
150 const FaceCreatedCallback& onCreated,
151 const FaceConnectFailedCallback& onConnectFailed)
152{
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600153 if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end())
154 {
155 onConnectFailed("Requested endpoint is prohibited "
156 "(reserved by this NFD or disallowed by face management protocol)");
157 return;
158 }
159
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800160 // very simple logic for now
161
162 for (ChannelMap::iterator channel = m_channels.begin();
163 channel != m_channels.end();
164 ++channel)
165 {
166 if ((channel->first.address().is_v4() && endpoint.address().is_v4()) ||
167 (channel->first.address().is_v6() && endpoint.address().is_v6()))
168 {
169 channel->second->connect(endpoint, onCreated, onConnectFailed);
170 return;
171 }
172 }
173 onConnectFailed("No channels available to connect to "
174 + boost::lexical_cast<std::string>(endpoint));
175}
176
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800177} // namespace nfd