blob: b987b5e30d0d422ecf87706757d5221e668adf3e [file] [log] [blame]
Giulio Grassi624f6c62014-02-18 19:42:14 +01001/* -*- 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
7#ifndef NFD_FACE_UDP_CHANNEL_HPP
8#define NFD_FACE_UDP_CHANNEL_HPP
9
10#include "common.hpp"
11#include "core/time.hpp"
12#include "udp-face.hpp"
13
14namespace nfd {
15
16namespace udp {
17 typedef boost::asio::ip::udp::endpoint Endpoint;
18} // namespace udp
19
20/**
21 * \brief Class implementing UDP-based channel to create faces
22 *
23 *
24 */
25class UdpChannel
26{
27public:
28
29 /**
30 * \brief Exception of UdpChannel
31 */
32 struct Error : public std::runtime_error
33 {
34 Error(const std::string& what) : runtime_error(what) {}
35 };
36
37 /**
38 * \brief Prototype for the callback called when face is created
39 * (as a response to new incoming communication not managed
40 * by any faces yet or after the connect function is created)
41 */
42 typedef function<void(const shared_ptr<UdpFace>& newFace)> FaceCreatedCallback;
43
44 /**
45 * \brief Prototype for the callback that is called when face is failed to
46 * get created
47 */
48 typedef function<void(const std::string& reason)> ConnectFailedCallback;
49
50 /**
51 * \brief Create UDP channel for the local endpoint
52 *
53 * To enable creation of faces upon incoming connections,
54 * one needs to explicitly call UdpChannel::listen method.
55 * The created socket is bound to the localEndpoint.
56 * reuse_address option is set
57 *
58 * \throw UdpChannel::Error if bind on the socket fails
59 */
60 UdpChannel(const udp::Endpoint& localEndpoint,
61 const time::Duration& timeout);
62
63 /**
64 * \brief Enable listening on the local endpoint, accept connections,
65 * and create faces when remote host makes a connection
66 * \param onFaceCreated Callback to notify successful creation of the face
67 * \param onAcceptFailed Callback to notify when channel fails
68 *
69 * \throws UdpChannel::Error if called multiple times
70 */
71 void
72 listen(const FaceCreatedCallback& onFaceCreated,
73 const ConnectFailedCallback& onAcceptFailed);
74
75 /**
76 * \brief Create a face by establishing connection to remote endpoint
77 *
78 * \throw UdpChannel::Error if bind or connect on the socket fail
79 */
80 void
81 connect(const udp::Endpoint& remoteEndpoint,
82 const FaceCreatedCallback& onFaceCreated);
83 /**
84 * \brief Create a face by establishing connection to the specified
85 * remote host and remote port
86 *
87 * This method will never block and will return immediately. All
88 * necessary hostname and port resolution and connection will happen
89 * in asynchronous mode.
90 *
91 * If connection cannot be established within specified timeout, it
92 * will be aborted.
93 */
94 void
95 connect(const std::string& remoteHost, const std::string& remotePort,
96 const FaceCreatedCallback& onFaceCreated,
97 const ConnectFailedCallback& onConnectFailed);
98
99 /**
100 * \brief Get number of faces in the channel
101 */
102 size_t
103 size() const;
104
105private:
106 shared_ptr<UdpFace>
107 createFace(const shared_ptr<boost::asio::ip::udp::socket>& socket,
108 const FaceCreatedCallback& onFaceCreated);
109 void
110 afterFaceFailed(udp::Endpoint& endpoint);
111
112 /**
113 * \brief The UdpChannel has received a new pkt from a remote endpoint not yet
114 * associated with any UdpFace
115 */
116 void
117 newPeer(const boost::system::error_code& error,
118 std::size_t nBytesReceived);
119
120 void
121 handleEndpointResolution(const boost::system::error_code& error,
122 boost::asio::ip::udp::resolver::iterator remoteEndpoint,
123 const FaceCreatedCallback& onFaceCreated,
124 const ConnectFailedCallback& onConnectFailed,
125 const shared_ptr<boost::asio::ip::udp::resolver>& resolver);
126
127private:
128 udp::Endpoint m_localEndpoint;
129
130 /**
131 * \brief Endpoint used to store the information about the last new remote endpoint
132 */
133 udp::Endpoint m_newRemoteEndpoint;
134
135 /**
136 * Callbacks for face creation.
137 * New communications are detected using async_receive_from.
138 * Its handler has a fixed signature. No space for the face callback
139 */
140 FaceCreatedCallback onFaceCreatedNewPeerCallback;
141
142 // @todo remove the onConnectFailedNewPeerCallback if it remains unused
143 ConnectFailedCallback onConnectFailedNewPeerCallback;
144
145 /**
146 * \brief Socket used to "accept" new communication
147 **/
148 shared_ptr<boost::asio::ip::udp::socket> m_socket;
149
150 uint8_t m_inputBuffer[MAX_NDN_PACKET_SIZE];
151
152 typedef std::map< udp::Endpoint, shared_ptr<UdpFace> > ChannelFaceMap;
153 ChannelFaceMap m_channelFaces;
154
155 /**
156 * \brief If true, it means the function listen has already been called
157 */
158 bool m_isListening;
159
160};
161
162} // namespace nfd
163
164#endif // NFD_FACE_UDP_CHANNEL_HPP