blob: a764a073375fc3a090d5100b6ca76ee5342130a7 [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 Afanasyeva9034b02014-01-26 18:32:02 -080037};
38
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080039template <class T>
40inline
Junxiao Shi8c8d2182014-01-30 22:33:00 -070041StreamFace<T>::StreamFace(const shared_ptr<typename StreamFace::protocol::socket>& socket)
42 : m_socket(socket)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080043{
44 m_socket->async_receive(boost::asio::buffer(m_inputBuffer, MAX_NDN_PACKET_SIZE), 0,
45 bind(&StreamFace<T>::handleReceive, this, _1, _2));
46}
47
48
49template <class T>
50inline void
51StreamFace<T>::handleSend(const boost::system::error_code& error,
52 const Block& wire)
53{
54 if (error) {
55 if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
56 return;
57
58 onFail("Send operation failed: " + error.category().message(error.value()));
59 m_socket->close();
60 return;
61 }
62
63 // do nothing (needed to retain validity of wire memory block
64}
65
66template <class T>
67inline void
68StreamFace<T>::handleReceive(const boost::system::error_code& error,
69 std::size_t bytes_recvd)
70{
71 if (error || bytes_recvd == 0) {
72 if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
73 return;
74
75 onFail("Receive operation failed: " + error.category().message(error.value()));
76 m_socket->close();
77 return;
78 }
79
80 m_inputBufferSize += bytes_recvd;
81 // do magic
82
83 std::size_t offset = 0;
84 /// @todo Eliminate reliance on exceptions in this path
85 try {
86 Block element(m_inputBuffer + offset, m_inputBufferSize - offset);
87 offset += element.size();
88
89 /// @todo Ensure lazy field decoding process
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080090 if (element.type() == tlv::Interest)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080091 {
92 shared_ptr<Interest> i = make_shared<Interest>();
93 i->wireDecode(element);
94 onReceiveInterest(*i);
95 }
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080096 else if (element.type() == tlv::Data)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080097 {
98 shared_ptr<Data> d = make_shared<Data>();
99 d->wireDecode(element);
100 onReceiveData(*d);
101 }
102 // @todo Add local header support
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800103 // else if (element.type() == tlv::LocalHeader)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800104 // {
105 // shared_ptr<Interest> i = make_shared<Interest>();
106 // i->wireDecode(element);
107 // }
108 else
109 {
110 /// @todo Add loggin
111
112 // ignore unknown packet and proceed
113 }
114 }
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800115 catch(const tlv::Error&) {
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800116 if (m_inputBufferSize == MAX_NDN_PACKET_SIZE && offset == 0)
117 {
118 onFail("Received input is invalid or too large to process, closing down the face");
119 m_socket->close();
120 return;
121 }
122 }
123
124 if (offset > 0)
125 {
126 if (offset != m_inputBufferSize)
127 {
128 std::copy(m_inputBuffer + offset, m_inputBuffer + m_inputBufferSize,
129 m_inputBuffer);
130 m_inputBufferSize -= offset;
131 }
132 else
133 {
134 m_inputBufferSize = 0;
135 }
136 }
137
138 m_socket->async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
139 MAX_NDN_PACKET_SIZE - m_inputBufferSize), 0,
140 bind(&StreamFace<T>::handleReceive, this, _1, _2));
141}
142
143
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800144} // namespace nfd
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800145
146#endif // NFD_FACE_STREAM_FACE_HPP