blob: 255e8ee8bf372976ee453986ec1646b2bffeae05 [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"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060032#include "core/logger.hpp"
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080033
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080034namespace nfd {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080035
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080036// forward declaration
37template<class T, class U, class V> struct StreamFaceSenderImpl;
38
39template<class Protocol, class FaceBase = Face>
40class StreamFace : public FaceBase
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080041{
42public:
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080043 typedef Protocol protocol;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080044
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080045 /**
46 * \brief Create instance of StreamFace
47 */
Junxiao Shi79494162014-04-02 18:25:11 -070048 StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
Alexander Afanasyev355c0662014-03-20 18:08:17 -070049 const shared_ptr<typename protocol::socket>& socket,
50 bool isOnDemand);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080051
Davide Pesavento66ff0982015-01-29 22:39:00 +010052 ~StreamFace() DECL_OVERRIDE;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080053
Davide Pesavento66ff0982015-01-29 22:39:00 +010054 // from FaceBase
55 void
56 sendInterest(const Interest& interest) DECL_OVERRIDE;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080057
Davide Pesavento66ff0982015-01-29 22:39:00 +010058 void
59 sendData(const Data& data) DECL_OVERRIDE;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080060
Davide Pesavento66ff0982015-01-29 22:39:00 +010061 void
62 close() DECL_OVERRIDE;
Alexander Afanasyev93ce75e2014-02-18 19:45:34 -080063
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080064protected:
65 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080066 processErrorCode(const boost::system::error_code& error);
67
68 void
Alexander Afanasyeve5966b72014-07-20 23:39:50 -070069 sendFromQueue();
70
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080071 void
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080072 handleSend(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -070073 size_t nBytesSent);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080074
75 void
76 handleReceive(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -070077 size_t nBytesReceived);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080078
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080079 void
Davide Pesavento3f5655f2014-08-30 21:38:59 +020080 shutdownSocket();
Davide Pesaventoba558e72014-02-17 18:38:19 +010081
82 void
Davide Pesavento3f5655f2014-08-30 21:38:59 +020083 deferredClose(const shared_ptr<Face>& face);
Davide Pesaventoba558e72014-02-17 18:38:19 +010084
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080085protected:
86 shared_ptr<typename protocol::socket> m_socket;
Davide Pesaventoba558e72014-02-17 18:38:19 +010087
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080088private:
Junxiao Shi39cd6332014-11-06 21:53:18 -070089 uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
Junxiao Shi5dd26c32014-07-20 23:15:14 -070090 size_t m_inputBufferSize;
Alexander Afanasyeve5966b72014-07-20 23:39:50 -070091 std::queue<Block> m_sendQueue;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080092
93 friend struct StreamFaceSenderImpl<Protocol, FaceBase, Interest>;
94 friend struct StreamFaceSenderImpl<Protocol, FaceBase, Data>;
95
Alexander Afanasyev3958b012014-01-31 15:06:13 -080096 NFD_LOG_INCLASS_DECLARE();
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080097};
98
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080099// All inherited classes must use
100// NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(StreamFace, <specialization-parameter>, "Name");
Alexander Afanasyev3958b012014-01-31 15:06:13 -0800101
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800102
103/** \brief Class allowing validation of the StreamFace use
104 *
105 * For example, partial specialization based on boost::asio::ip::tcp should check
106 * that local endpoint is loopback
107 *
108 * @throws Face::Error if validation failed
109 */
110template<class Protocol, class U>
111struct StreamFaceValidator
112{
113 static void
114 validateSocket(typename Protocol::socket& socket)
115 {
116 }
117};
118
119
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000120template<class T, class FaceBase>
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800121inline
Junxiao Shi79494162014-04-02 18:25:11 -0700122StreamFace<T, FaceBase>::StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
123 const shared_ptr<typename StreamFace::protocol::socket>& socket,
124 bool isOnDemand)
125 : FaceBase(remoteUri, localUri)
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000126 , m_socket(socket)
Alexander Afanasyevb9f6e432014-02-14 20:52:49 -0800127 , m_inputBufferSize(0)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800128{
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700129 FaceBase::setOnDemand(isOnDemand);
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000130 StreamFaceValidator<T, FaceBase>::validateSocket(*socket);
Junxiao Shi39cd6332014-11-06 21:53:18 -0700131 m_socket->async_receive(boost::asio::buffer(m_inputBuffer, ndn::MAX_NDN_PACKET_SIZE), 0,
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000132 bind(&StreamFace<T, FaceBase>::handleReceive, this, _1, _2));
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800133}
134
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800135template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800136inline
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800137StreamFace<T, U>::~StreamFace()
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800138{
139}
140
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200141
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800142template<class Protocol, class FaceBase, class Packet>
143struct StreamFaceSenderImpl
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800144{
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800145 static void
146 send(StreamFace<Protocol, FaceBase>& face, const Packet& packet)
147 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700148 bool wasQueueEmpty = face.m_sendQueue.empty();
149 face.m_sendQueue.push(packet.wireEncode());
150
151 if (wasQueueEmpty)
152 face.sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800153 }
154};
155
156// partial specialization (only classes can be partially specialized)
157template<class Protocol, class Packet>
158struct StreamFaceSenderImpl<Protocol, LocalFace, Packet>
159{
160 static void
161 send(StreamFace<Protocol, LocalFace>& face, const Packet& packet)
162 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700163 bool wasQueueEmpty = face.m_sendQueue.empty();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800164
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700165 if (!face.isEmptyFilteredLocalControlHeader(packet.getLocalControlHeader()))
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800166 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700167 face.m_sendQueue.push(face.filterAndEncodeLocalControlHeader(packet));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800168 }
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700169 face.m_sendQueue.push(packet.wireEncode());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800170
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700171 if (wasQueueEmpty)
172 face.sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800173 }
174};
175
176
177template<class T, class U>
178inline void
179StreamFace<T, U>::sendInterest(const Interest& interest)
180{
Junxiao Shic099ddb2014-12-25 20:53:20 -0700181 this->emitSignal(onSendInterest, interest);
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800182 StreamFaceSenderImpl<T, U, Interest>::send(*this, interest);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800183}
184
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800185template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800186inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800187StreamFace<T, U>::sendData(const Data& data)
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800188{
Junxiao Shic099ddb2014-12-25 20:53:20 -0700189 this->emitSignal(onSendData, data);
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800190 StreamFaceSenderImpl<T, U, Data>::send(*this, data);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800191}
192
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800193template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800194inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800195StreamFace<T, U>::close()
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800196{
197 if (!m_socket->is_open())
198 return;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800199
Davide Pesavento66ff0982015-01-29 22:39:00 +0100200 NFD_LOG_INFO("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
201 << "] Closing face");
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800202
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200203 shutdownSocket();
Davide Pesavento66ff0982015-01-29 22:39:00 +0100204 this->fail("Face closed");
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800205}
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800206
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800207template<class T, class U>
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800208inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800209StreamFace<T, U>::processErrorCode(const boost::system::error_code& error)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800210{
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200211 if (error == boost::asio::error::operation_aborted || // when cancel() is called
212 error == boost::asio::error::shut_down) // after shutdown() is called
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800213 return;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800214
215 if (!m_socket->is_open())
216 {
Junxiao Shi08d07a72014-06-09 23:17:57 -0700217 this->fail("Connection closed");
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800218 return;
219 }
220
Davide Pesavento66ff0982015-01-29 22:39:00 +0100221 if (error != boost::asio::error::eof)
222 NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
223 << "] Send or receive operation failed, closing face: "
224 << error.message());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800225
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200226 shutdownSocket();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800227
228 if (error == boost::asio::error::eof)
229 {
Junxiao Shi08d07a72014-06-09 23:17:57 -0700230 this->fail("Connection closed");
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800231 }
232 else
233 {
Davide Pesavento66ff0982015-01-29 22:39:00 +0100234 this->fail("Send or receive operation failed: " + error.message());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800235 }
236}
237
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200238template<class T, class U>
239inline void
240StreamFace<T, U>::sendFromQueue()
241{
242 const Block& block = this->m_sendQueue.front();
243 boost::asio::async_write(*this->m_socket, boost::asio::buffer(block),
244 bind(&StreamFace<T, U>::handleSend, this, _1, _2));
245}
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800246
247template<class T, class U>
248inline void
249StreamFace<T, U>::handleSend(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700250 size_t nBytesSent)
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800251{
252 if (error)
253 return processErrorCode(error);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800254
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700255 BOOST_ASSERT(!m_sendQueue.empty());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800256
Davide Pesavento66ff0982015-01-29 22:39:00 +0100257 NFD_LOG_TRACE("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700258 << "] Successfully sent: " << nBytesSent << " bytes");
259 this->getMutableCounters().getNOutBytes() += nBytesSent;
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700260
261 m_sendQueue.pop();
262 if (!m_sendQueue.empty())
263 sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800264}
265
266template<class T, class U>
267inline void
268StreamFace<T, U>::handleReceive(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700269 size_t nBytesReceived)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800270{
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800271 if (error)
272 return processErrorCode(error);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800273
Davide Pesavento66ff0982015-01-29 22:39:00 +0100274 NFD_LOG_TRACE("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700275 << "] Received: " << nBytesReceived << " bytes");
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700276 this->getMutableCounters().getNInBytes() += nBytesReceived;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800277
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700278 m_inputBufferSize += nBytesReceived;
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800279
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700280 size_t offset = 0;
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800281
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700282 bool isOk = true;
283 Block element;
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700284 while (m_inputBufferSize - offset > 0)
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700285 {
286 isOk = Block::fromBuffer(m_inputBuffer + offset, m_inputBufferSize - offset, element);
287 if (!isOk)
288 break;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800289
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700290 offset += element.size();
Davide Pesaventoba558e72014-02-17 18:38:19 +0100291
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700292 BOOST_ASSERT(offset <= m_inputBufferSize);
293
294 if (!this->decodeAndDispatchInput(element))
295 {
Davide Pesavento66ff0982015-01-29 22:39:00 +0100296 NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700297 << "] Received unrecognized block of type ["
298 << element.type() << "]");
299 // ignore unknown packet and proceed
300 }
301 }
Junxiao Shi39cd6332014-11-06 21:53:18 -0700302 if (!isOk && m_inputBufferSize == ndn::MAX_NDN_PACKET_SIZE && offset == 0)
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700303 {
Davide Pesavento66ff0982015-01-29 22:39:00 +0100304 NFD_LOG_WARN("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200305 << "] Failed to parse incoming packet or packet too large to process, "
Davide Pesavento66ff0982015-01-29 22:39:00 +0100306 << "closing face");
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200307 shutdownSocket();
Davide Pesavento66ff0982015-01-29 22:39:00 +0100308 this->fail("Failed to parse incoming packet or packet too large to process");
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700309 return;
310 }
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800311
312 if (offset > 0)
313 {
314 if (offset != m_inputBufferSize)
315 {
316 std::copy(m_inputBuffer + offset, m_inputBuffer + m_inputBufferSize,
317 m_inputBuffer);
318 m_inputBufferSize -= offset;
319 }
320 else
321 {
322 m_inputBufferSize = 0;
323 }
324 }
325
326 m_socket->async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
Junxiao Shi39cd6332014-11-06 21:53:18 -0700327 ndn::MAX_NDN_PACKET_SIZE - m_inputBufferSize), 0,
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800328 bind(&StreamFace<T, U>::handleReceive, this, _1, _2));
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800329}
330
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800331template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800332inline void
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200333StreamFace<T, U>::shutdownSocket()
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800334{
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200335 // Cancel all outstanding operations and shutdown the socket
336 // so that no further sends or receives are possible.
337 // Use the non-throwing variants and ignore errors, if any.
338 boost::system::error_code error;
339 m_socket->cancel(error);
340 m_socket->shutdown(protocol::socket::shutdown_both, error);
341
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200342 // ensure that the Face object is alive at least until all pending
343 // handlers are dispatched
Davide Pesavento66ff0982015-01-29 22:39:00 +0100344 getGlobalIoService().post(bind(&StreamFace<T, U>::deferredClose,
345 this, this->shared_from_this()));
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200346
347 // Some bug or feature of Boost.Asio (see http://redmine.named-data.net/issues/1856):
348 //
349 // When shutdownSocket is called from within a socket event (e.g., from handleReceive),
350 // m_socket->shutdown() does not trigger the cancellation of the handleSend callback.
351 // Instead, handleSend is invoked as nothing bad happened.
352 //
353 // In order to prevent the assertion in handleSend from failing, we clear the queue
354 // and close the socket in deferredClose, i.e., after all callbacks scheduled up to
355 // this point have been executed. If more send operations are scheduled after this
356 // point, they will fail because the socket has been shutdown, and their callbacks
357 // will be invoked with error code == asio::error::shut_down.
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800358}
359
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800360template<class T, class U>
Davide Pesaventoba558e72014-02-17 18:38:19 +0100361inline void
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200362StreamFace<T, U>::deferredClose(const shared_ptr<Face>& face)
Davide Pesaventoba558e72014-02-17 18:38:19 +0100363{
Davide Pesavento66ff0982015-01-29 22:39:00 +0100364 NFD_LOG_DEBUG("[id:" << this->getId() << ",uri:" << this->getRemoteUri()
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200365 << "] Clearing send queue");
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700366
367 // clear send queue
368 std::queue<Block> emptyQueue;
369 std::swap(emptyQueue, m_sendQueue);
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200370
371 // use the non-throwing variant and ignore errors, if any
372 boost::system::error_code error;
373 m_socket->close(error);
Davide Pesaventoba558e72014-02-17 18:38:19 +0100374}
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800375
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800376} // namespace nfd
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800377
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700378#endif // NFD_DAEMON_FACE_STREAM_FACE_HPP