blob: 45b1a485228dc1fe368e7d041ba69ac3d384afa2 [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 Afanasyev7329e022014-02-27 14:47:22 -08008#include "core/global-io.hpp"
Alexander Afanasyevd6655302014-02-28 08:41:28 -08009#include "core/resolver.hpp"
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080010
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080011namespace nfd {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080012
Alexander Afanasyevd6655302014-02-28 08:41:28 -080013TcpFactory::TcpFactory(const std::string& defaultPort/* = "6363"*/)
14 : m_defaultPort(defaultPort)
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080015{
Alexander Afanasyevd6655302014-02-28 08:41:28 -080016}
17
18shared_ptr<TcpChannel>
19TcpFactory::createChannel(const tcp::Endpoint& endpoint)
20{
21 shared_ptr<TcpChannel> channel = findChannel(endpoint);
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080022 if(static_cast<bool>(channel))
23 return channel;
24
Alexander Afanasyev7329e022014-02-27 14:47:22 -080025 channel = make_shared<TcpChannel>(boost::ref(getGlobalIoService()), boost::cref(endpoint));
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080026 m_channels[endpoint] = channel;
27 return channel;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080028}
29
30shared_ptr<TcpChannel>
Alexander Afanasyevd6655302014-02-28 08:41:28 -080031TcpFactory::createChannel(const std::string& localHost, const std::string& localPort)
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080032{
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080033 using boost::asio::ip::tcp;
Alexander Afanasyev7329e022014-02-27 14:47:22 -080034
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080035 tcp::resolver::query query(localHost, localPort);
Alexander Afanasyev7329e022014-02-27 14:47:22 -080036 tcp::resolver resolver(getGlobalIoService());
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080037
38 tcp::resolver::iterator end;
39 tcp::resolver::iterator i = resolver.resolve(query);
40 if (i == end)
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080041 return shared_ptr<TcpChannel>();
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080042
Alexander Afanasyevd6655302014-02-28 08:41:28 -080043 return createChannel(*i);
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080044}
45
46shared_ptr<TcpChannel>
Alexander Afanasyevd6655302014-02-28 08:41:28 -080047TcpFactory::findChannel(const tcp::Endpoint& localEndpoint)
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080048{
Alexander Afanasyev8ad71ba2014-01-27 00:07:14 -080049 ChannelMap::iterator i = m_channels.find(localEndpoint);
50 if (i != m_channels.end())
51 return i->second;
52 else
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080053 return shared_ptr<TcpChannel>();
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080054}
55
Alexander Afanasyevd6655302014-02-28 08:41:28 -080056void
57TcpFactory::createFace(const FaceUri& uri,
58 const FaceCreatedCallback& onCreated,
59 const FaceConnectFailedCallback& onConnectFailed)
60{
61 resolver::AddressSelector addressSelector = resolver::AnyAddress();
62 if (uri.getScheme() == "tcp4")
63 addressSelector = resolver::Ipv4Address();
64 else if (uri.getScheme() == "tcp6")
65 addressSelector = resolver::Ipv6Address();
66
67 using boost::asio::ip::tcp;
68 Resolver<tcp>::asyncResolve(uri.getDomain(),
69 uri.getPort().empty() ? m_defaultPort : uri.getPort(),
70 bind(&TcpFactory::continueCreateFaceAfterResolve, this, _1,
71 onCreated, onConnectFailed),
72 onConnectFailed,
73 addressSelector);
74}
75
76void
77TcpFactory::continueCreateFaceAfterResolve(const tcp::Endpoint& endpoint,
78 const FaceCreatedCallback& onCreated,
79 const FaceConnectFailedCallback& onConnectFailed)
80{
81 // very simple logic for now
82
83 for (ChannelMap::iterator channel = m_channels.begin();
84 channel != m_channels.end();
85 ++channel)
86 {
87 if ((channel->first.address().is_v4() && endpoint.address().is_v4()) ||
88 (channel->first.address().is_v6() && endpoint.address().is_v6()))
89 {
90 channel->second->connect(endpoint, onCreated, onConnectFailed);
91 return;
92 }
93 }
94 onConnectFailed("No channels available to connect to "
95 + boost::lexical_cast<std::string>(endpoint));
96}
97
98
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080099} // namespace nfd