comparison DEPENDENCIES/generic/include/boost/asio/detail/impl/socket_select_interrupter.ipp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 //
2 // detail/impl/socket_select_interrupter.ipp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2013 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
35 namespace boost {
36 namespace asio {
37 namespace detail {
38
39 socket_select_interrupter::socket_select_interrupter()
40 {
41 open_descriptors();
42 }
43
44 void 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 = inet_addr("127.0.0.1");
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 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
76
77 if (socket_ops::listen(acceptor.get(),
78 SOMAXCONN, ec) == socket_error_retval)
79 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
80
81 socket_holder client(socket_ops::socket(
82 AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
83 if (client.get() == invalid_socket)
84 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
85
86 if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
87 addr_len, ec) == socket_error_retval)
88 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
89
90 socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
91 if (server.get() == invalid_socket)
92 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
93
94 ioctl_arg_type non_blocking = 1;
95 socket_ops::state_type client_state = 0;
96 if (socket_ops::ioctl(client.get(), client_state,
97 FIONBIO, &non_blocking, ec))
98 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
99
100 opt = 1;
101 socket_ops::setsockopt(client.get(), client_state,
102 IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
103
104 non_blocking = 1;
105 socket_ops::state_type server_state = 0;
106 if (socket_ops::ioctl(server.get(), server_state,
107 FIONBIO, &non_blocking, ec))
108 boost::asio::detail::throw_error(ec, "socket_select_interrupter");
109
110 opt = 1;
111 socket_ops::setsockopt(server.get(), server_state,
112 IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
113
114 read_descriptor_ = server.release();
115 write_descriptor_ = client.release();
116 }
117
118 socket_select_interrupter::~socket_select_interrupter()
119 {
120 close_descriptors();
121 }
122
123 void socket_select_interrupter::close_descriptors()
124 {
125 boost::system::error_code ec;
126 socket_ops::state_type state = socket_ops::internal_non_blocking;
127 if (read_descriptor_ != invalid_socket)
128 socket_ops::close(read_descriptor_, state, true, ec);
129 if (write_descriptor_ != invalid_socket)
130 socket_ops::close(write_descriptor_, state, true, ec);
131 }
132
133 void socket_select_interrupter::recreate()
134 {
135 close_descriptors();
136
137 write_descriptor_ = invalid_socket;
138 read_descriptor_ = invalid_socket;
139
140 open_descriptors();
141 }
142
143 void socket_select_interrupter::interrupt()
144 {
145 char byte = 0;
146 socket_ops::buf b;
147 socket_ops::init_buf(b, &byte, 1);
148 boost::system::error_code ec;
149 socket_ops::send(write_descriptor_, &b, 1, 0, ec);
150 }
151
152 bool socket_select_interrupter::reset()
153 {
154 char data[1024];
155 socket_ops::buf b;
156 socket_ops::init_buf(b, data, sizeof(data));
157 boost::system::error_code ec;
158 int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
159 bool was_interrupted = (bytes_read > 0);
160 while (bytes_read == sizeof(data))
161 bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
162 return was_interrupted;
163 }
164
165 } // namespace detail
166 } // namespace asio
167 } // namespace boost
168
169 #include <boost/asio/detail/pop_options.hpp>
170
171 #endif // defined(BOOST_ASIO_WINDOWS)
172 // || defined(__CYGWIN__)
173 // || defined(__SYMBIAN32__)
174
175 #endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
176
177 #endif // BOOST_ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP