Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / asio / detail / impl / socket_select_interrupter.ipp @ 2486

History | View | Annotate | Download (5.5 kB)

1
//
2
// detail/impl/socket_select_interrupter.ipp
3
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
//
5
// Copyright (c) 2003-2015 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 = 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
  addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK);
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