blob: fb51afd1b3174f4dcfe393f21de6f086181809d4 [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
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080033namespace nfd {
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080034
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080035// forward declaration
36template<class T, class U, class V> struct StreamFaceSenderImpl;
37
38template<class Protocol, class FaceBase = Face>
39class StreamFace : public FaceBase
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080040{
41public:
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080042 typedef Protocol protocol;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080043
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080044 /**
45 * \brief Create instance of StreamFace
46 */
Junxiao Shi79494162014-04-02 18:25:11 -070047 StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
Alexander Afanasyev355c0662014-03-20 18:08:17 -070048 const shared_ptr<typename protocol::socket>& socket,
49 bool isOnDemand);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080050
Davide Pesavento66ff0982015-01-29 22:39:00 +010051 // from FaceBase
52 void
53 sendInterest(const Interest& interest) DECL_OVERRIDE;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080054
Davide Pesavento66ff0982015-01-29 22:39:00 +010055 void
56 sendData(const Data& data) DECL_OVERRIDE;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080057
Davide Pesavento66ff0982015-01-29 22:39:00 +010058 void
59 close() DECL_OVERRIDE;
Alexander Afanasyev93ce75e2014-02-18 19:45:34 -080060
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080061protected:
62 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080063 processErrorCode(const boost::system::error_code& error);
64
65 void
Alexander Afanasyeve5966b72014-07-20 23:39:50 -070066 sendFromQueue();
67
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080068 void
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080069 handleSend(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -070070 size_t nBytesSent);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080071
72 void
73 handleReceive(const boost::system::error_code& error,
Junxiao Shi5dd26c32014-07-20 23:15:14 -070074 size_t nBytesReceived);
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080075
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080076 void
Davide Pesavento3f5655f2014-08-30 21:38:59 +020077 shutdownSocket();
Davide Pesaventoba558e72014-02-17 18:38:19 +010078
79 void
Davide Pesavento3f5655f2014-08-30 21:38:59 +020080 deferredClose(const shared_ptr<Face>& face);
Davide Pesaventoba558e72014-02-17 18:38:19 +010081
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080082protected:
83 shared_ptr<typename protocol::socket> m_socket;
Davide Pesaventoba558e72014-02-17 18:38:19 +010084
Davide Pesaventobe40fb12015-02-23 21:09:34 +010085 NFD_LOG_INCLASS_DECLARE();
86
Alexander Afanasyevd32cb962014-01-28 12:43:47 -080087private:
Junxiao Shi39cd6332014-11-06 21:53:18 -070088 uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
Junxiao Shi5dd26c32014-07-20 23:15:14 -070089 size_t m_inputBufferSize;
Alexander Afanasyeve5966b72014-07-20 23:39:50 -070090 std::queue<Block> m_sendQueue;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080091
92 friend struct StreamFaceSenderImpl<Protocol, FaceBase, Interest>;
93 friend struct StreamFaceSenderImpl<Protocol, FaceBase, Data>;
Alexander Afanasyeva9034b02014-01-26 18:32:02 -080094};
95
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080096// All inherited classes must use
97// NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(StreamFace, <specialization-parameter>, "Name");
Alexander Afanasyev3958b012014-01-31 15:06:13 -080098
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080099
100/** \brief Class allowing validation of the StreamFace use
101 *
102 * For example, partial specialization based on boost::asio::ip::tcp should check
103 * that local endpoint is loopback
104 *
105 * @throws Face::Error if validation failed
106 */
107template<class Protocol, class U>
108struct StreamFaceValidator
109{
110 static void
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100111 validateSocket(const typename Protocol::socket& socket)
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800112 {
113 }
114};
115
116
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000117template<class T, class FaceBase>
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800118inline
Junxiao Shi79494162014-04-02 18:25:11 -0700119StreamFace<T, FaceBase>::StreamFace(const FaceUri& remoteUri, const FaceUri& localUri,
Davide Pesavento94279412015-02-27 01:29:32 +0100120 const shared_ptr<typename StreamFace::protocol::socket>& socket,
121 bool isOnDemand)
Junxiao Shi79494162014-04-02 18:25:11 -0700122 : FaceBase(remoteUri, localUri)
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000123 , m_socket(socket)
Alexander Afanasyevb9f6e432014-02-14 20:52:49 -0800124 , m_inputBufferSize(0)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800125{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100126 NFD_LOG_FACE_INFO("Creating face");
127
Davide Pesavento94279412015-02-27 01:29:32 +0100128 this->setOnDemand(isOnDemand);
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000129 StreamFaceValidator<T, FaceBase>::validateSocket(*socket);
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100130
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
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200135
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800136template<class Protocol, class FaceBase, class Packet>
137struct StreamFaceSenderImpl
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800138{
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800139 static void
140 send(StreamFace<Protocol, FaceBase>& face, const Packet& packet)
141 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700142 bool wasQueueEmpty = face.m_sendQueue.empty();
143 face.m_sendQueue.push(packet.wireEncode());
144
145 if (wasQueueEmpty)
146 face.sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800147 }
148};
149
150// partial specialization (only classes can be partially specialized)
151template<class Protocol, class Packet>
152struct StreamFaceSenderImpl<Protocol, LocalFace, Packet>
153{
154 static void
155 send(StreamFace<Protocol, LocalFace>& face, const Packet& packet)
156 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700157 bool wasQueueEmpty = face.m_sendQueue.empty();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800158
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700159 if (!face.isEmptyFilteredLocalControlHeader(packet.getLocalControlHeader()))
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800160 {
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700161 face.m_sendQueue.push(face.filterAndEncodeLocalControlHeader(packet));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800162 }
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700163 face.m_sendQueue.push(packet.wireEncode());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800164
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700165 if (wasQueueEmpty)
166 face.sendFromQueue();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800167 }
168};
169
170
171template<class T, class U>
172inline void
173StreamFace<T, U>::sendInterest(const Interest& interest)
174{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100175 NFD_LOG_FACE_TRACE(__func__);
Junxiao Shic099ddb2014-12-25 20:53:20 -0700176 this->emitSignal(onSendInterest, interest);
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800177 StreamFaceSenderImpl<T, U, Interest>::send(*this, interest);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800178}
179
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800180template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800181inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800182StreamFace<T, U>::sendData(const Data& data)
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800183{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100184 NFD_LOG_FACE_TRACE(__func__);
Junxiao Shic099ddb2014-12-25 20:53:20 -0700185 this->emitSignal(onSendData, data);
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800186 StreamFaceSenderImpl<T, U, Data>::send(*this, data);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800187}
188
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800189template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800190inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800191StreamFace<T, U>::close()
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800192{
193 if (!m_socket->is_open())
194 return;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800195
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100196 NFD_LOG_FACE_INFO("Closing face");
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800197
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200198 shutdownSocket();
Davide Pesavento66ff0982015-01-29 22:39:00 +0100199 this->fail("Face closed");
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800200}
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800201
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800202template<class T, class U>
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800203inline void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800204StreamFace<T, U>::processErrorCode(const boost::system::error_code& error)
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800205{
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200206 if (error == boost::asio::error::operation_aborted || // when cancel() is called
207 error == boost::asio::error::shut_down) // after shutdown() is called
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800208 return;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800209
210 if (!m_socket->is_open())
211 {
Junxiao Shi08d07a72014-06-09 23:17:57 -0700212 this->fail("Connection closed");
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800213 return;
214 }
215
Davide Pesavento66ff0982015-01-29 22:39:00 +0100216 if (error != boost::asio::error::eof)
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100217 NFD_LOG_FACE_WARN("Send or receive operation failed: " << error.message());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800218
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200219 shutdownSocket();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800220
221 if (error == boost::asio::error::eof)
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100222 this->fail("Connection closed");
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800223 else
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100224 this->fail(error.message());
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800225}
226
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200227template<class T, class U>
228inline void
229StreamFace<T, U>::sendFromQueue()
230{
231 const Block& block = this->m_sendQueue.front();
232 boost::asio::async_write(*this->m_socket, boost::asio::buffer(block),
233 bind(&StreamFace<T, U>::handleSend, this, _1, _2));
234}
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 Shi5dd26c32014-07-20 23:15:14 -0700271 while (m_inputBufferSize - offset > 0)
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700272 {
273 isOk = Block::fromBuffer(m_inputBuffer + offset, m_inputBufferSize - offset, element);
274 if (!isOk)
275 break;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800276
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700277 offset += element.size();
Davide Pesaventoba558e72014-02-17 18:38:19 +0100278
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700279 BOOST_ASSERT(offset <= m_inputBufferSize);
280
281 if (!this->decodeAndDispatchInput(element))
282 {
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100283 NFD_LOG_FACE_WARN("Received unrecognized TLV block of type " << element.type());
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700284 // ignore unknown packet and proceed
285 }
286 }
Junxiao Shi39cd6332014-11-06 21:53:18 -0700287 if (!isOk && m_inputBufferSize == ndn::MAX_NDN_PACKET_SIZE && offset == 0)
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700288 {
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100289 NFD_LOG_FACE_WARN("Failed to parse incoming packet or packet too large to process");
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200290 shutdownSocket();
Davide Pesavento66ff0982015-01-29 22:39:00 +0100291 this->fail("Failed to parse incoming packet or packet too large to process");
Alexander Afanasyev5a8d8d82014-03-21 14:08:41 -0700292 return;
293 }
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800294
295 if (offset > 0)
296 {
297 if (offset != m_inputBufferSize)
298 {
299 std::copy(m_inputBuffer + offset, m_inputBuffer + m_inputBufferSize,
300 m_inputBuffer);
301 m_inputBufferSize -= offset;
302 }
303 else
304 {
305 m_inputBufferSize = 0;
306 }
307 }
308
309 m_socket->async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
Junxiao Shi39cd6332014-11-06 21:53:18 -0700310 ndn::MAX_NDN_PACKET_SIZE - m_inputBufferSize), 0,
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800311 bind(&StreamFace<T, U>::handleReceive, this, _1, _2));
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800312}
313
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800314template<class T, class U>
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800315inline void
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200316StreamFace<T, U>::shutdownSocket()
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800317{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100318 NFD_LOG_FACE_TRACE(__func__);
319
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200320 // Cancel all outstanding operations and shutdown the socket
321 // so that no further sends or receives are possible.
322 // Use the non-throwing variants and ignore errors, if any.
323 boost::system::error_code error;
324 m_socket->cancel(error);
325 m_socket->shutdown(protocol::socket::shutdown_both, error);
326
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200327 // ensure that the Face object is alive at least until all pending
328 // handlers are dispatched
Davide Pesavento66ff0982015-01-29 22:39:00 +0100329 getGlobalIoService().post(bind(&StreamFace<T, U>::deferredClose,
330 this, this->shared_from_this()));
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200331
332 // Some bug or feature of Boost.Asio (see http://redmine.named-data.net/issues/1856):
333 //
334 // When shutdownSocket is called from within a socket event (e.g., from handleReceive),
335 // m_socket->shutdown() does not trigger the cancellation of the handleSend callback.
336 // Instead, handleSend is invoked as nothing bad happened.
337 //
338 // In order to prevent the assertion in handleSend from failing, we clear the queue
339 // and close the socket in deferredClose, i.e., after all callbacks scheduled up to
340 // this point have been executed. If more send operations are scheduled after this
341 // point, they will fail because the socket has been shutdown, and their callbacks
342 // will be invoked with error code == asio::error::shut_down.
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800343}
344
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800345template<class T, class U>
Davide Pesaventoba558e72014-02-17 18:38:19 +0100346inline void
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200347StreamFace<T, U>::deferredClose(const shared_ptr<Face>& face)
Davide Pesaventoba558e72014-02-17 18:38:19 +0100348{
Davide Pesaventobe40fb12015-02-23 21:09:34 +0100349 NFD_LOG_FACE_TRACE(__func__);
Alexander Afanasyeve5966b72014-07-20 23:39:50 -0700350
351 // clear send queue
352 std::queue<Block> emptyQueue;
353 std::swap(emptyQueue, m_sendQueue);
Davide Pesavento3f5655f2014-08-30 21:38:59 +0200354
355 // use the non-throwing variant and ignore errors, if any
356 boost::system::error_code error;
357 m_socket->close(error);
Davide Pesaventoba558e72014-02-17 18:38:19 +0100358}
Alexander Afanasyevd32cb962014-01-28 12:43:47 -0800359
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800360} // namespace nfd
Alexander Afanasyeva9034b02014-01-26 18:32:02 -0800361
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700362#endif // NFD_DAEMON_FACE_STREAM_FACE_HPP