blob: 5580fe4eefdb996d430820edbf11a656a9876320 [file] [log] [blame]
Alexander Afanasyeva9034b02014-01-26 18:32:02 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Junxiao Shi5dd26c32014-07-20 23:15:14 -070024 */
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080025
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070026#ifndef NFD_DAEMON_FACE_STREAM_FACE_HPP
27#define NFD_DAEMON_FACE_STREAM_FACE_HPP
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080028
29#include "face.hpp"
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080030#include "local-face.hpp"
Davide Pesavento66ff0982015-01-29 22:39:00 +010031#include "core/global-io.hpp"
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080032
Davide Pesaventod2856a42015-09-19 21:29:50 +020033#include <queue>
34
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080035namespace nfd {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080036
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080037// forward declaration
38template<class T, class U, class V> struct StreamFaceSenderImpl;
39
40template<class Protocol, class FaceBase = Face>
41class StreamFace : public FaceBase
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080042{
43public:
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080044 typedef Protocol protocol;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080045
Junxiao Shi79494162014-04-02 18:25:11 -070046 StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
Davide Pesavento292e5e12015-03-13 02:08:33 +010047 typename protocol::socket socket, bool isOnDemand);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080048
Davide Pesavento66ff0982015-01-29 22:39:00 +010049 // from FaceBase
50 void
51 sendInterest(const Interest& interest) DECL_OVERRIDE;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080052
Davide Pesavento66ff0982015-01-29 22:39:00 +010053 void
54 sendData(const Data& data) DECL_OVERRIDE;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080055
Davide Pesavento66ff0982015-01-29 22:39:00 +010056 void
57 close() DECL_OVERRIDE;
Alexander Afanasyev93ce75e2014-02-18 19:45:34 -080058
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080059protected:
60 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080061 processErrorCode(const boost::system::error_code& error);
62
63 void
Alexander Afanasyeve5966b72014-07-20 23:39:50 -070064 sendFromQueue();
65
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080066 void
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080067 handleSend(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -070068 size_t nBytesSent);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080069
70 void
71 handleReceive(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -070072 size_t nBytesReceived);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080073
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080074 void
Davide Pesavento3f5655f2014-08-30 21:38:59 +020075 shutdownSocket();
Davide Pesaventoba558e72014-02-17 18:38:19 +010076
77 void
Davide Pesavento3f5655f2014-08-30 21:38:59 +020078 deferredClose(const shared_ptr<Face>& face);
Davide Pesaventoba558e72014-02-17 18:38:19 +010079
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080080protected:
Davide Pesavento292e5e12015-03-13 02:08:33 +010081 typename protocol::socket m_socket;
Davide Pesaventoba558e72014-02-17 18:38:19 +010082
Davide Pesaventobe40fb12015-02-23 21:09:34 +010083 NFD_LOG_INCLASS_DECLARE();
84
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080085private:
Junxiao Shi39cd6332014-11-06 21:53:18 -070086 uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
Junxiao Shi5dd26c32014-07-20 23:15:14 -070087 size_t m_inputBufferSize;
Alexander Afanasyeve5966b72014-07-20 23:39:50 -070088 std::queue<Block> m_sendQueue;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080089
90 friend struct StreamFaceSenderImpl<Protocol, FaceBase, Interest>;
91 friend struct StreamFaceSenderImpl<Protocol, FaceBase, Data>;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080092};
93
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080094// All inherited classes must use
95// NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(StreamFace, <specialization-parameter>, "Name");
Alexander Afanasyev3958b012014-01-31 15:06:13 -080096
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080097
98/** \brief Class allowing validation of the StreamFace use
99 *
100 * For example, partial specialization based on boost::asio::ip::tcp should check
101 * that local endpoint is loopback
102 *
103 * @throws Face::Error if validation failed
104 */
105template<class Protocol, class U>
106struct StreamFaceValidator
107{
108 static void
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100109 validateSocket(const typename Protocol::socket& socket)
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800110 {
111 }
112};
113
114
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000115template<class T, class FaceBase>
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800116inline
Junxiao Shi79494162014-04-02 18:25:11 -0700117StreamFace<T, FaceBase>::StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
Davide Pesavento292e5e12015-03-13 02:08:33 +0100118 typename StreamFace::protocol::socket socket, bool isOnDemand)
Junxiao Shi79494162014-04-02 18:25:11 -0700119 : FaceBase(remoteUri, localUri)
Davide Pesavento292e5e12015-03-13 02:08:33 +0100120 , m_socket(std::move(socket))
Alexander Afanasyevb9f6e432014-02-14 20:52:49 -0800121 , m_inputBufferSize(0)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800122{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100123 NFD_LOG_FACE_INFO("Creating face");
124
Yukai Tu731f0d72015-07-04 11:14:44 +0800125 this->setPersistency(isOnDemand ? ndn::nfd::FACE_PERSISTENCY_ON_DEMAND : ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
Davide Pesavento292e5e12015-03-13 02:08:33 +0100126 StreamFaceValidator<T, FaceBase>::validateSocket(m_socket);
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100127
Davide Pesavento292e5e12015-03-13 02:08:33 +0100128 m_socket.async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE),
129 bind(&StreamFace<T, FaceBase>::handleReceive, this,
130 boost::asio::placeholders::error,
131 boost::asio::placeholders::bytes_transferred));
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800132}
133
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200134
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800135template<class Protocol, class FaceBase, class Packet>
136struct StreamFaceSenderImpl
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800137{
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800138 static void
139 send(StreamFace<Protocol, FaceBase>& face, const Packet& packet)
140 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700141 bool wasQueueEmpty = face.m_sendQueue.empty();
142 face.m_sendQueue.push(packet.wireEncode());
143
144 if (wasQueueEmpty)
145 face.sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800146 }
147};
148
149// partial specialization (only classes can be partially specialized)
150template<class Protocol, class Packet>
151struct StreamFaceSenderImpl<Protocol, LocalFace, Packet>
152{
153 static void
154 send(StreamFace<Protocol, LocalFace>& face, const Packet& packet)
155 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700156 bool wasQueueEmpty = face.m_sendQueue.empty();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800157
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700158 if (!face.isEmptyFilteredLocalControlHeader(packet.getLocalControlHeader()))
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800159 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700160 face.m_sendQueue.push(face.filterAndEncodeLocalControlHeader(packet));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800161 }
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700162 face.m_sendQueue.push(packet.wireEncode());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800163
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700164 if (wasQueueEmpty)
165 face.sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800166 }
167};
168
169
170template<class T, class U>
171inline void
172StreamFace<T, U>::sendInterest(const Interest& interest)
173{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100174 NFD_LOG_FACE_TRACE(__func__);
Junxiao Shic099ddb2014-12-25 20:53:20 -0700175 this->emitSignal(onSendInterest, interest);
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800176 StreamFaceSenderImpl<T, U, Interest>::send(*this, interest);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800177}
178
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800179template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800180inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800181StreamFace<T, U>::sendData(const Data& data)
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800182{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100183 NFD_LOG_FACE_TRACE(__func__);
Junxiao Shic099ddb2014-12-25 20:53:20 -0700184 this->emitSignal(onSendData, data);
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800185 StreamFaceSenderImpl<T, U, Data>::send(*this, data);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800186}
187
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800188template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800189inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800190StreamFace<T, U>::close()
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800191{
Davide Pesavento292e5e12015-03-13 02:08:33 +0100192 if (!m_socket.is_open())
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800193 return;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800194
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100195 NFD_LOG_FACE_INFO("Closing face");
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800196
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200197 shutdownSocket();
Davide Pesavento66ff0982015-01-29 22:39:00 +0100198 this->fail("Face closed");
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800199}
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800200
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800201template<class T, class U>
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800202inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800203StreamFace<T, U>::processErrorCode(const boost::system::error_code& error)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800204{
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200205 if (error == boost::asio::error::operation_aborted || // when cancel() is called
206 error == boost::asio::error::shut_down) // after shutdown() is called
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800207 return;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800208
Davide Pesavento292e5e12015-03-13 02:08:33 +0100209 if (!m_socket.is_open())
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800210 {
Junxiao Shi08d07a72014-06-09 23:17:57 -0700211 this->fail("Connection closed");
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800212 return;
213 }
214
Davide Pesavento66ff0982015-01-29 22:39:00 +0100215 if (error != boost::asio::error::eof)
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100216 NFD_LOG_FACE_WARN("Send or receive operation failed: " << error.message());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800217
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200218 shutdownSocket();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800219
220 if (error == boost::asio::error::eof)
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100221 this->fail("Connection closed");
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800222 else
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100223 this->fail(error.message());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800224}
225
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200226template<class T, class U>
227inline void
228StreamFace<T, U>::sendFromQueue()
229{
Davide Pesavento292e5e12015-03-13 02:08:33 +0100230 boost::asio::async_write(m_socket, boost::asio::buffer(m_sendQueue.front()),
231 bind(&StreamFace<T, U>::handleSend, this,
232 boost::asio::placeholders::error,
233 boost::asio::placeholders::bytes_transferred));
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200234}
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800235
236template<class T, class U>
237inline void
238StreamFace<T, U>::handleSend(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700239 size_t nBytesSent)
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800240{
241 if (error)
242 return processErrorCode(error);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800243
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700244 BOOST_ASSERT(!m_sendQueue.empty());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800245
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100246 NFD_LOG_FACE_TRACE("Successfully sent: " << nBytesSent << " bytes");
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700247 this->getMutableCounters().getNOutBytes() += nBytesSent;
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700248
249 m_sendQueue.pop();
250 if (!m_sendQueue.empty())
251 sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800252}
253
254template<class T, class U>
255inline void
256StreamFace<T, U>::handleReceive(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700257 size_t nBytesReceived)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800258{
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800259 if (error)
260 return processErrorCode(error);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800261
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100262 NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes");
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700263 this->getMutableCounters().getNInBytes() += nBytesReceived;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800264
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700265 m_inputBufferSize += nBytesReceived;
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800266
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700267 size_t offset = 0;
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800268
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700269 bool isOk = true;
270 Block element;
Junxiao Shi78926c92015-02-28 22:56:06 -0700271 while (m_inputBufferSize - offset > 0) {
272 std::tie(isOk, element) = Block::fromBuffer(m_inputBuffer + offset, m_inputBufferSize - offset);
273 if (!isOk)
274 break;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800275
Junxiao Shi78926c92015-02-28 22:56:06 -0700276 offset += element.size();
Davide Pesaventoba558e72014-02-17 18:38:19 +0100277
Junxiao Shi78926c92015-02-28 22:56:06 -0700278 BOOST_ASSERT(offset <= m_inputBufferSize);
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700279
Junxiao Shi78926c92015-02-28 22:56:06 -0700280 if (!this->decodeAndDispatchInput(element)) {
281 NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << element.type());
282 // ignore unknown packet and proceed
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700283 }
Junxiao Shi78926c92015-02-28 22:56:06 -0700284 }
285
Junxiao Shi39cd6332014-11-06 21:53:18 -0700286 if (!isOk && m_inputBufferSize == ndn::MAX_NDN_PACKET_SIZE && offset == 0)
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700287 {
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100288 NFD_LOG_FACE_WARN("Failed to parse incoming packet or packet too large to process");
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200289 shutdownSocket();
Davide Pesavento66ff0982015-01-29 22:39:00 +0100290 this->fail("Failed to parse incoming packet or packet too large to process");
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700291 return;
292 }
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800293
294 if (offset > 0)
295 {
296 if (offset != m_inputBufferSize)
297 {
298 std::copy(m_inputBuffer + offset, m_inputBuffer + m_inputBufferSize,
299 m_inputBuffer);
300 m_inputBufferSize -= offset;
301 }
302 else
303 {
304 m_inputBufferSize = 0;
305 }
306 }
307
Davide Pesavento292e5e12015-03-13 02:08:33 +0100308 m_socket.async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
309 ndn::MAX_NDN_PACKET_SIZE - m_inputBufferSize),
310 bind(&StreamFace<T, U>::handleReceive, this,
311 boost::asio::placeholders::error,
312 boost::asio::placeholders::bytes_transferred));
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800313}
314
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800315template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800316inline void
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200317StreamFace<T, U>::shutdownSocket()
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800318{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100319 NFD_LOG_FACE_TRACE(__func__);
320
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200321 // Cancel all outstanding operations and shutdown the socket
322 // so that no further sends or receives are possible.
323 // Use the non-throwing variants and ignore errors, if any.
324 boost::system::error_code error;
Davide Pesavento292e5e12015-03-13 02:08:33 +0100325 m_socket.cancel(error);
326 m_socket.shutdown(protocol::socket::shutdown_both, error);
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200327
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200328 // ensure that the Face object is alive at least until all pending
329 // handlers are dispatched
Davide Pesavento66ff0982015-01-29 22:39:00 +0100330 getGlobalIoService().post(bind(&StreamFace<T, U>::deferredClose,
331 this, this->shared_from_this()));
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200332
333 // Some bug or feature of Boost.Asio (see http://redmine.named-data.net/issues/1856):
334 //
335 // When shutdownSocket is called from within a socket event (e.g., from handleReceive),
Davide Pesavento292e5e12015-03-13 02:08:33 +0100336 // m_socket.shutdown() does not trigger the cancellation of the handleSend callback.
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200337 // Instead, handleSend is invoked as nothing bad happened.
338 //
339 // In order to prevent the assertion in handleSend from failing, we clear the queue
340 // and close the socket in deferredClose, i.e., after all callbacks scheduled up to
341 // this point have been executed. If more send operations are scheduled after this
342 // point, they will fail because the socket has been shutdown, and their callbacks
343 // will be invoked with error code == asio::error::shut_down.
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800344}
345
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800346template<class T, class U>
Davide Pesaventoba558e72014-02-17 18:38:19 +0100347inline void
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200348StreamFace<T, U>::deferredClose(const shared_ptr<Face>& face)
Davide Pesaventoba558e72014-02-17 18:38:19 +0100349{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100350 NFD_LOG_FACE_TRACE(__func__);
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700351
352 // clear send queue
353 std::queue<Block> emptyQueue;
354 std::swap(emptyQueue, m_sendQueue);
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200355
356 // use the non-throwing variant and ignore errors, if any
357 boost::system::error_code error;
Davide Pesavento292e5e12015-03-13 02:08:33 +0100358 m_socket.close(error);
Davide Pesaventoba558e72014-02-17 18:38:19 +0100359}
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800360
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800361} // namespace nfd
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800362
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700363#endif // NFD_DAEMON_FACE_STREAM_FACE_HPP