PageRenderTime 36ms CodeModel.GetById 29ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/asio/detail/impl/socket_select_interrupter.ipp

http://hadesmem.googlecode.com/
C++ Header | 173 lines | 126 code | 33 blank | 14 comment | 25 complexity | dc73f2236e8859891b5f7ef01da4effe MD5 | raw file
  1//
  2// detail/impl/socket_select_interrupter.ipp
  3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4//
  5// Copyright (c) 2003-2011 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_WINDOWS) \
 21  || defined(__CYGWIN__) \
 22  || defined(__SYMBIAN32__)
 23
 24#include <cstdlib>
 25#include <boost/asio/detail/socket_holder.hpp>
 26#include <boost/asio/detail/socket_ops.hpp>
 27#include <boost/asio/detail/socket_select_interrupter.hpp>
 28#include <boost/asio/detail/throw_error.hpp>
 29#include <boost/asio/error.hpp>
 30
 31#include <boost/asio/detail/push_options.hpp>
 32
 33namespace boost {
 34namespace asio {
 35namespace detail {
 36
 37socket_select_interrupter::socket_select_interrupter()
 38{
 39  open_descriptors();
 40}
 41
 42void socket_select_interrupter::open_descriptors()
 43{
 44  boost::system::error_code ec;
 45  socket_holder acceptor(socket_ops::socket(
 46        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
 47  if (acceptor.get() == invalid_socket)
 48    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 49
 50  int opt = 1;
 51  socket_ops::state_type acceptor_state = 0;
 52  socket_ops::setsockopt(acceptor.get(), acceptor_state,
 53      SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
 54
 55  using namespace std; // For memset.
 56  sockaddr_in4_type addr;
 57  std::size_t addr_len = sizeof(addr);
 58  memset(&addr, 0, sizeof(addr));
 59  addr.sin_family = AF_INET;
 60  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 61  addr.sin_port = 0;
 62  if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
 63        addr_len, ec) == socket_error_retval)
 64    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 65
 66  if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
 67        &addr_len, ec) == socket_error_retval)
 68    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 69
 70  // Some broken firewalls on Windows will intermittently cause getsockname to
 71  // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We
 72  // explicitly specify the target address here to work around this problem.
 73  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 74
 75  if (socket_ops::listen(acceptor.get(),
 76        SOMAXCONN, ec) == socket_error_retval)
 77    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 78
 79  socket_holder client(socket_ops::socket(
 80        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
 81  if (client.get() == invalid_socket)
 82    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 83
 84  if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
 85        addr_len, ec) == socket_error_retval)
 86    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 87
 88  socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
 89  if (server.get() == invalid_socket)
 90    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 91  
 92  ioctl_arg_type non_blocking = 1;
 93  socket_ops::state_type client_state = 0;
 94  if (socket_ops::ioctl(client.get(), client_state,
 95        FIONBIO, &non_blocking, ec))
 96    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
 97
 98  opt = 1;
 99  socket_ops::setsockopt(client.get(), client_state,
100      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
101
102  non_blocking = 1;
103  socket_ops::state_type server_state = 0;
104  if (socket_ops::ioctl(server.get(), server_state,
105        FIONBIO, &non_blocking, ec))
106    boost::asio::detail::throw_error(ec, "socket_select_interrupter");
107
108  opt = 1;
109  socket_ops::setsockopt(server.get(), server_state,
110      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
111
112  read_descriptor_ = server.release();
113  write_descriptor_ = client.release();
114}
115
116socket_select_interrupter::~socket_select_interrupter()
117{
118  close_descriptors();
119}
120
121void socket_select_interrupter::close_descriptors()
122{
123  boost::system::error_code ec;
124  socket_ops::state_type state = socket_ops::internal_non_blocking;
125  if (read_descriptor_ != invalid_socket)
126    socket_ops::close(read_descriptor_, state, true, ec);
127  if (write_descriptor_ != invalid_socket)
128    socket_ops::close(write_descriptor_, state, true, ec);
129}
130
131void socket_select_interrupter::recreate()
132{
133  close_descriptors();
134
135  write_descriptor_ = invalid_socket;
136  read_descriptor_ = invalid_socket;
137
138  open_descriptors();
139}
140
141void socket_select_interrupter::interrupt()
142{
143  char byte = 0;
144  socket_ops::buf b;
145  socket_ops::init_buf(b, &byte, 1);
146  boost::system::error_code ec;
147  socket_ops::send(write_descriptor_, &b, 1, 0, ec);
148}
149
150bool socket_select_interrupter::reset()
151{
152  char data[1024];
153  socket_ops::buf b;
154  socket_ops::init_buf(b, data, sizeof(data));
155  boost::system::error_code ec;
156  int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
157  bool was_interrupted = (bytes_read > 0);
158  while (bytes_read == sizeof(data))
159    bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
160  return was_interrupted;
161}
162
163} // namespace detail
164} // namespace asio
165} // namespace boost
166
167#include <boost/asio/detail/pop_options.hpp>
168
169#endif // defined(BOOST_WINDOWS)
170       // || defined(__CYGWIN__)
171       // || defined(__SYMBIAN32__)
172
173#endif // BOOST_ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP