blob: 428d33e0ec6c294b9455c98a895600293bd1970b [file] [log] [blame]
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +01001/* -*- 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#include "unix-stream-channel.hpp"
8
9#include <boost/filesystem.hpp>
10
11namespace nfd {
12
13NFD_LOG_INIT("UnixStreamChannel");
14
15using namespace boost::asio::local;
16
17UnixStreamChannel::UnixStreamChannel(boost::asio::io_service& ioService,
18 const unix_stream::Endpoint& endpoint)
19 : m_ioService(ioService)
20 , m_endpoint(endpoint)
21{
22}
23
24UnixStreamChannel::~UnixStreamChannel()
25{
26 if (m_acceptor)
27 {
28 // use the non-throwing variants during destruction
29 // and ignore any errors
30 boost::system::error_code error;
31 m_acceptor->close(error);
32 boost::filesystem::remove(m_endpoint.path(), error);
33 }
34}
35
36void
37UnixStreamChannel::listen(const FaceCreatedCallback& onFaceCreated,
38 const ConnectFailedCallback& onAcceptFailed,
39 int backlog/* = acceptor::max_connections*/)
40{
41 if (m_acceptor) // already listening
42 return;
43
44 namespace fs = boost::filesystem;
45 fs::path p(m_endpoint.path());
46 if (fs::symlink_status(p).type() == fs::socket_file)
47 {
48 // for safety, remove an already existing file only if it's a socket
49 fs::remove(p);
50 }
51
52 m_acceptor = make_shared<stream_protocol::acceptor>(boost::ref(m_ioService));
53 m_acceptor->open(m_endpoint.protocol());
54 m_acceptor->bind(m_endpoint);
55 m_acceptor->listen(backlog);
56
57 shared_ptr<stream_protocol::socket> clientSocket =
58 make_shared<stream_protocol::socket>(boost::ref(m_ioService));
59 m_acceptor->async_accept(*clientSocket,
60 bind(&UnixStreamChannel::handleSuccessfulAccept, this, _1,
61 clientSocket, onFaceCreated, onAcceptFailed));
62}
63
64void
65UnixStreamChannel::createFace(const shared_ptr<stream_protocol::socket>& socket,
66 const FaceCreatedCallback& onFaceCreated)
67{
68 shared_ptr<UnixStreamFace> face = make_shared<UnixStreamFace>(boost::cref(socket));
69 onFaceCreated(face);
70}
71
72void
73UnixStreamChannel::handleSuccessfulAccept(const boost::system::error_code& error,
74 const shared_ptr<stream_protocol::socket>& socket,
75 const FaceCreatedCallback& onFaceCreated,
76 const ConnectFailedCallback& onAcceptFailed)
77{
78 if (error) {
79 if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
80 return;
81
82 NFD_LOG_DEBUG("Connection failed: "
83 << error.category().message(error.value()));
84
85 onAcceptFailed("Connection failed: " +
86 error.category().message(error.value()));
87 return;
88 }
89
90 // prepare accepting the next connection
91 shared_ptr<stream_protocol::socket> clientSocket =
92 make_shared<stream_protocol::socket>(boost::ref(m_ioService));
93 m_acceptor->async_accept(*clientSocket,
94 bind(&UnixStreamChannel::handleSuccessfulAccept, this, _1,
95 clientSocket, onFaceCreated, onAcceptFailed));
96
97 NFD_LOG_DEBUG("[" << m_endpoint << "] << Incoming connection");
98 createFace(socket, onFaceCreated);
99}
100
101} // namespace nfd