]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/asio/include/boost/asio/detail/impl/socket_select_interrupter.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / asio / include / boost / asio / detail / impl / socket_select_interrupter.ipp
CommitLineData
7c673cae
FG
1//
2// detail/impl/socket_select_interrupter.ipp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
12#define BOOST_ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19
20#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
21
22#if defined(BOOST_ASIO_WINDOWS) \
23 || defined(__CYGWIN__) \
24 || defined(__SYMBIAN32__)
25
26#include <cstdlib>
27#include <boost/asio/detail/socket_holder.hpp>
28#include <boost/asio/detail/socket_ops.hpp>
29#include <boost/asio/detail/socket_select_interrupter.hpp>
30#include <boost/asio/detail/throw_error.hpp>
31#include <boost/asio/error.hpp>
32
33#include <boost/asio/detail/push_options.hpp>
34
35namespace boost {
36namespace asio {
37namespace detail {
38
39socket_select_interrupter::socket_select_interrupter()
40{
41 open_descriptors();
42}
43
44void socket_select_interrupter::open_descriptors()
45{
46 boost::system::error_code ec;
47 socket_holder acceptor(socket_ops::socket(
48 AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
49 if (acceptor.get() == invalid_socket)
50 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
51
52 int opt = 1;
53 socket_ops::state_type acceptor_state = 0;
54 socket_ops::setsockopt(acceptor.get(), acceptor_state,
55 SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
56
57 using namespace std; // For memset.
58 sockaddr_in4_type addr;
59 std::size_t addr_len = sizeof(addr);
60 memset(&addr, 0, sizeof(addr));
61 addr.sin_family = AF_INET;
62 addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK);
63 addr.sin_port = 0;
64 if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
65 addr_len, ec) == socket_error_retval)
66 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
67
68 if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
69 &addr_len, ec) == socket_error_retval)
70 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
71
72 // Some broken firewalls on Windows will intermittently cause getsockname to
73 // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We
74 // explicitly specify the target address here to work around this problem.
75 if (addr.sin_addr.s_addr == socket_ops::host_to_network_long(INADDR_ANY))
76 addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK);
77
78 if (socket_ops::listen(acceptor.get(),
79 SOMAXCONN, ec) == socket_error_retval)
80 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
81
82 socket_holder client(socket_ops::socket(
83 AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
84 if (client.get() == invalid_socket)
85 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
86
87 if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
88 addr_len, ec) == socket_error_retval)
89 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
90
91 socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
92 if (server.get() == invalid_socket)
93 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
94
95 ioctl_arg_type non_blocking = 1;
96 socket_ops::state_type client_state = 0;
97 if (socket_ops::ioctl(client.get(), client_state,
98 FIONBIO, &non_blocking, ec))
99 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
100
101 opt = 1;
102 socket_ops::setsockopt(client.get(), client_state,
103 IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
104
105 non_blocking = 1;
106 socket_ops::state_type server_state = 0;
107 if (socket_ops::ioctl(server.get(), server_state,
108 FIONBIO, &non_blocking, ec))
109 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
110
111 opt = 1;
112 socket_ops::setsockopt(server.get(), server_state,
113 IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
114
115 read_descriptor_ = server.release();
116 write_descriptor_ = client.release();
117}
118
119socket_select_interrupter::~socket_select_interrupter()
120{
121 close_descriptors();
122}
123
124void socket_select_interrupter::close_descriptors()
125{
126 boost::system::error_code ec;
127 socket_ops::state_type state = socket_ops::internal_non_blocking;
128 if (read_descriptor_ != invalid_socket)
129 socket_ops::close(read_descriptor_, state, true, ec);
130 if (write_descriptor_ != invalid_socket)
131 socket_ops::close(write_descriptor_, state, true, ec);
132}
133
134void socket_select_interrupter::recreate()
135{
136 close_descriptors();
137
138 write_descriptor_ = invalid_socket;
139 read_descriptor_ = invalid_socket;
140
141 open_descriptors();
142}
143
144void socket_select_interrupter::interrupt()
145{
146 char byte = 0;
147 socket_ops::buf b;
148 socket_ops::init_buf(b, &byte, 1);
149 boost::system::error_code ec;
150 socket_ops::send(write_descriptor_, &b, 1, 0, ec);
151}
152
153bool socket_select_interrupter::reset()
154{
155 char data[1024];
156 socket_ops::buf b;
157 socket_ops::init_buf(b, data, sizeof(data));
158 boost::system::error_code ec;
159 int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
160 bool was_interrupted = (bytes_read > 0);
161 while (bytes_read == sizeof(data))
162 bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
163 return was_interrupted;
164}
165
166} // namespace detail
167} // namespace asio
168} // namespace boost
169
170#include <boost/asio/detail/pop_options.hpp>
171
172#endif // defined(BOOST_ASIO_WINDOWS)
173 // || defined(__CYGWIN__)
174 // || defined(__SYMBIAN32__)
175
176#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
177
178#endif // BOOST_ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP