blob: 529e3ef2c3067be8b6df12a13fff4c6842147b76 [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
7#ifndef NFD_FACE_STREAM_FACE_HPP
8#define NFD_FACE_STREAM_FACE_HPP
9
10#include "face.hpp"
11
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080012namespace nfd {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080013
14template <class T>
15class StreamFace : public Face
16{
17public:
18 typedef T protocol;
19
Junxiao Shi8c8d2182014-01-30 22:33:00 -070020 StreamFace(const shared_ptr<typename protocol::socket>& socket);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080021
22protected:
23 void
24 handleSend(const boost::system::error_code& error,
25 const Block& wire);
26
27 void
28 handleReceive(const boost::system::error_code& error,
29 std::size_t bytes_recvd);
30
31protected:
32 shared_ptr<typename protocol::socket> m_socket;
33
34private:
35 uint8_t m_inputBuffer[MAX_NDN_PACKET_SIZE];
36 std::size_t m_inputBufferSize;
Alexander Afanasyev3958b012014-01-31 15:06:13 -080037
38 NFD_LOG_INCLASS_DECLARE();
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080039};
40
Alexander Afanasyev3958b012014-01-31 15:06:13 -080041NFD_LOG_INCLASS_TEMPLATE_DEFINE(StreamFace, "StreamFace");
42
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080043template <class T>
44inline
Junxiao Shi8c8d2182014-01-30 22:33:00 -070045StreamFace<T>::StreamFace(const shared_ptr<typename StreamFace::protocol::socket>& socket)
46 : m_socket(socket)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080047{
48 m_socket->async_receive(boost::asio::buffer(m_inputBuffer, MAX_NDN_PACKET_SIZE), 0,
49 bind(&StreamFace<T>::handleReceive, this, _1, _2));
50}
51
52
53template <class T>
54inline void
55StreamFace<T>::handleSend(const boost::system::error_code& error,
56 const Block& wire)
57{
58 if (error) {
59 if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
60 return;
61
Alexander Afanasyev3958b012014-01-31 15:06:13 -080062 NFD_LOG_WARN("[id:" << this->getId()
63 << ",endpoint:" << m_socket->local_endpoint()
64 << "] Send operation failed, closing socket: "
65 << error.category().message(error.value()));
66
67 onFail("Send operation failed, closing socket: " +
68 error.category().message(error.value()));
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080069 m_socket->close();
70 return;
71 }
72
Alexander Afanasyev3958b012014-01-31 15:06:13 -080073 NFD_LOG_TRACE("[id:" << this->getId()
74 << ",endpoint:" << m_socket->local_endpoint()
75 << "] Successfully sent: " << wire.size() << " bytes");
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080076 // do nothing (needed to retain validity of wire memory block
77}
78
79template <class T>
80inline void
81StreamFace<T>::handleReceive(const boost::system::error_code& error,
82 std::size_t bytes_recvd)
83{
Alexander Afanasyev3958b012014-01-31 15:06:13 -080084 NFD_LOG_TRACE("[id:" << this->getId()
85 << ",endpoint:" << m_socket->local_endpoint()
86 << "] Received: " << bytes_recvd << " bytes");
87
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080088 if (error || bytes_recvd == 0) {
89 if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
90 return;
91
Alexander Afanasyev3958b012014-01-31 15:06:13 -080092 NFD_LOG_WARN("[id:" << this->getId()
93 << ",endpoint:" << m_socket->local_endpoint()
94 << "] Receive operation failed: "
95 << error.category().message(error.value()));
96
97 onFail("Receive operation failed, closing socket: " +
98 error.category().message(error.value()));
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080099 m_socket->close();
100 return;
101 }
102
103 m_inputBufferSize += bytes_recvd;
104 // do magic
105
106 std::size_t offset = 0;
107 /// @todo Eliminate reliance on exceptions in this path
108 try {
Alexander Afanasyev3958b012014-01-31 15:06:13 -0800109 while(m_inputBufferSize - offset > 0)
110 {
111 Block element(m_inputBuffer + offset, m_inputBufferSize - offset);
112 offset += element.size();
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800113
Alexander Afanasyev3958b012014-01-31 15:06:13 -0800114 BOOST_ASSERT(offset <= m_inputBufferSize);
115
116 /// @todo Ensure lazy field decoding process
117 if (element.type() == tlv::Interest)
118 {
119 shared_ptr<Interest> i = make_shared<Interest>();
120 i->wireDecode(element);
121 onReceiveInterest(*i);
122 }
123 else if (element.type() == tlv::Data)
124 {
125 shared_ptr<Data> d = make_shared<Data>();
126 d->wireDecode(element);
127 onReceiveData(*d);
128 }
129 // @todo Add local header support
130 // else if (element.type() == tlv::LocalHeader)
131 // {
132 // shared_ptr<Interest> i = make_shared<Interest>();
133 // i->wireDecode(element);
134 // }
135 else
136 {
137 NFD_LOG_WARN("[id:" << this->getId()
138 << ",endpoint:" << m_socket->local_endpoint()
139 << "] Received unrecognized block of type ["
140 << element.type() << "]");
141 // ignore unknown packet and proceed
142 }
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800143 }
144 }
Alexander Afanasyev3958b012014-01-31 15:06:13 -0800145 catch(const tlv::Error& e) {
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800146 if (m_inputBufferSize == MAX_NDN_PACKET_SIZE && offset == 0)
147 {
Alexander Afanasyev3958b012014-01-31 15:06:13 -0800148 NFD_LOG_WARN("[id:" << this->getId()
149 << ",endpoint:" << m_socket->local_endpoint()
150 << "] Received input is invalid or too large to process, "
151 << "closing down the face");
152
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800153 onFail("Received input is invalid or too large to process, closing down the face");
154 m_socket->close();
155 return;
156 }
157 }
158
159 if (offset > 0)
160 {
161 if (offset != m_inputBufferSize)
162 {
163 std::copy(m_inputBuffer + offset, m_inputBuffer + m_inputBufferSize,
164 m_inputBuffer);
165 m_inputBufferSize -= offset;
166 }
167 else
168 {
169 m_inputBufferSize = 0;
170 }
171 }
172
173 m_socket->async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
174 MAX_NDN_PACKET_SIZE - m_inputBufferSize), 0,
175 bind(&StreamFace<T>::handleReceive, this, _1, _2));
176}
177
178
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800179} // namespace nfd
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800180
181#endif // NFD_FACE_STREAM_FACE_HPP