⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reactive_socket_service.hpp

📁 这是国外的resip协议栈
💻 HPP
📖 第 1 页 / 共 4 页
字号:
//// reactive_socket_service.hpp// ~~~~~~~~~~~~~~~~~~~~~~~~~~~//// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)//// Distributed under the Boost Software License, Version 1.0. (See accompanying// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP#if defined(_MSC_VER) && (_MSC_VER >= 1200)# pragma once#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)#include "asio/detail/push_options.hpp"#include "asio/detail/push_options.hpp"#include <boost/shared_ptr.hpp>#include "asio/detail/pop_options.hpp"#include "asio/buffer.hpp"#include "asio/error.hpp"#include "asio/io_service.hpp"#include "asio/socket_base.hpp"#include "asio/detail/bind_handler.hpp"#include "asio/detail/noncopyable.hpp"#include "asio/detail/service_base.hpp"#include "asio/detail/socket_holder.hpp"#include "asio/detail/socket_ops.hpp"#include "asio/detail/socket_types.hpp"namespace asio {namespace detail {template <typename Protocol, typename Reactor>class reactive_socket_service  : public asio::detail::service_base<      reactive_socket_service<Protocol, Reactor> >{public:  // The protocol type.  typedef Protocol protocol_type;  // The endpoint type.  typedef typename Protocol::endpoint endpoint_type;  // The native type of a socket.  typedef socket_type native_type;  // The implementation type of the socket.  class implementation_type    : private asio::detail::noncopyable  {  public:    // Default constructor.    implementation_type()      : socket_(invalid_socket),        flags_(0),        protocol_(endpoint_type().protocol())    {    }  private:    // Only this service will have access to the internal values.    friend class reactive_socket_service<Protocol, Reactor>;    // The native socket representation.    socket_type socket_;    enum    {      user_set_non_blocking = 1, // The user wants a non-blocking socket.      internal_non_blocking = 2, // The socket has been set non-blocking.      enable_connection_aborted = 4, // User wants connection_aborted errors.      user_set_linger = 8 // The user set the linger option.    };    // Flags indicating the current state of the socket.    unsigned char flags_;    // The protocol associated with the socket.    protocol_type protocol_;  };  // The maximum number of buffers to support in a single operation.  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };  // Constructor.  reactive_socket_service(asio::io_service& io_service)    : asio::detail::service_base<        reactive_socket_service<Protocol, Reactor> >(io_service),      reactor_(asio::use_service<Reactor>(io_service))  {  }  // Destroy all user-defined handler objects owned by the service.  void shutdown_service()  {  }  // Construct a new socket implementation.  void construct(implementation_type& impl)  {    impl.socket_ = invalid_socket;    impl.flags_ = 0;  }  // Destroy a socket implementation.  void destroy(implementation_type& impl)  {    if (impl.socket_ != invalid_socket)    {      reactor_.close_descriptor(impl.socket_);      if (impl.flags_ & implementation_type::internal_non_blocking)      {        ioctl_arg_type non_blocking = 0;        asio::error_code ignored_ec;        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);        impl.flags_ &= ~implementation_type::internal_non_blocking;      }      if (impl.flags_ & implementation_type::user_set_linger)      {        ::linger opt;        opt.l_onoff = 0;        opt.l_linger = 0;        asio::error_code ignored_ec;        socket_ops::setsockopt(impl.socket_,            SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);      }      asio::error_code ignored_ec;      socket_ops::close(impl.socket_, ignored_ec);      impl.socket_ = invalid_socket;    }  }  // Open a new socket implementation.  asio::error_code open(implementation_type& impl,      const protocol_type& protocol, asio::error_code& ec)  {    if (is_open(impl))    {      ec = asio::error::already_open;      return ec;    }    socket_holder sock(socket_ops::socket(protocol.family(),          protocol.type(), protocol.protocol(), ec));    if (sock.get() == invalid_socket)      return ec;    if (int err = reactor_.register_descriptor(sock.get()))    {      ec = asio::error_code(err,          asio::error::get_system_category());      return ec;    }    impl.socket_ = sock.release();    impl.flags_ = 0;    impl.protocol_ = protocol;    ec = asio::error_code();    return ec;  }  // Assign a native socket to a socket implementation.  asio::error_code assign(implementation_type& impl,      const protocol_type& protocol, const native_type& native_socket,      asio::error_code& ec)  {    if (is_open(impl))    {      ec = asio::error::already_open;      return ec;    }    if (int err = reactor_.register_descriptor(native_socket))    {      ec = asio::error_code(err,          asio::error::get_system_category());      return ec;    }    impl.socket_ = native_socket;    impl.flags_ = 0;    impl.protocol_ = protocol;    ec = asio::error_code();    return ec;  }  // Determine whether the socket is open.  bool is_open(const implementation_type& impl) const  {    return impl.socket_ != invalid_socket;  }  // Destroy a socket implementation.  asio::error_code close(implementation_type& impl,      asio::error_code& ec)  {    if (is_open(impl))    {      reactor_.close_descriptor(impl.socket_);      if (impl.flags_ & implementation_type::internal_non_blocking)      {        ioctl_arg_type non_blocking = 0;        asio::error_code ignored_ec;        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);        impl.flags_ &= ~implementation_type::internal_non_blocking;      }      if (socket_ops::close(impl.socket_, ec) == socket_error_retval)        return ec;      impl.socket_ = invalid_socket;    }    ec = asio::error_code();    return ec;  }  // Get the native socket representation.  native_type native(implementation_type& impl)  {    return impl.socket_;  }  // Cancel all operations associated with the socket.  asio::error_code cancel(implementation_type& impl,      asio::error_code& ec)  {    if (!is_open(impl))    {      ec = asio::error::bad_descriptor;      return ec;    }    reactor_.cancel_ops(impl.socket_);    ec = asio::error_code();    return ec;  }  // Determine whether the socket is at the out-of-band data mark.  bool at_mark(const implementation_type& impl,      asio::error_code& ec) const  {    if (!is_open(impl))    {      ec = asio::error::bad_descriptor;      return false;    }    asio::detail::ioctl_arg_type value = 0;    socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);#if defined(ENOTTY)    if (ec.value() == ENOTTY)      ec = asio::error::not_socket;#endif // defined(ENOTTY)    return ec ? false : value != 0;  }  // Determine the number of bytes available for reading.  std::size_t available(const implementation_type& impl,      asio::error_code& ec) const  {    if (!is_open(impl))    {      ec = asio::error::bad_descriptor;      return 0;    }    asio::detail::ioctl_arg_type value = 0;    socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);#if defined(ENOTTY)    if (ec.value() == ENOTTY)      ec = asio::error::not_socket;#endif // defined(ENOTTY)    return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);  }  // Bind the socket to the specified local endpoint.  asio::error_code bind(implementation_type& impl,      const endpoint_type& endpoint, asio::error_code& ec)  {    if (!is_open(impl))    {      ec = asio::error::bad_descriptor;      return ec;    }    socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);    return ec;  }  // Place the socket into the state where it will listen for new connections.  asio::error_code listen(implementation_type& impl, int backlog,      asio::error_code& ec)  {    if (!is_open(impl))    {      ec = asio::error::bad_descriptor;      return ec;    }    socket_ops::listen(impl.socket_, backlog, ec);    return ec;  }  // Set a socket option.  template <typename Option>  asio::error_code set_option(implementation_type& impl,      const Option& option, asio::error_code& ec)  {    if (!is_open(impl))    {      ec = asio::error::bad_descriptor;      return ec;    }    if (option.level(impl.protocol_) == custom_socket_option_level        && option.name(impl.protocol_) == enable_connection_aborted_option)    {      if (option.size(impl.protocol_) != sizeof(int))      {        ec = asio::error::invalid_argument;      }      else      {        if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))          impl.flags_ |= implementation_type::enable_connection_aborted;        else          impl.flags_ &= ~implementation_type::enable_connection_aborted;        ec = asio::error_code();      }      return ec;    }    else    {      if (option.level(impl.protocol_) == SOL_SOCKET          && option.name(impl.protocol_) == SO_LINGER)      {        impl.flags_ |= implementation_type::user_set_linger;      }      socket_ops::setsockopt(impl.socket_,          option.level(impl.protocol_), option.name(impl.protocol_),          option.data(impl.protocol_), option.size(impl.protocol_), ec);#if defined(__MACH__) && defined(__APPLE__) \|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)      // To implement portable behaviour for SO_REUSEADDR with UDP sockets we      // need to also set SO_REUSEPORT on BSD-based platforms.      if (!ec && impl.protocol_.type() == SOCK_DGRAM          && option.level(impl.protocol_) == SOL_SOCKET          && option.name(impl.protocol_) == SO_REUSEADDR)      {        asio::error_code ignored_ec;        socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT,            option.data(impl.protocol_), option.size(impl.protocol_),            ignored_ec);      }#endif      return ec;    }  }  // Set a socket option.  template <typename Option>  asio::error_code get_option(const implementation_type& impl,      Option& option, asio::error_code& ec) const  {    if (!is_open(impl))    {      ec = asio::error::bad_descriptor;      return ec;    }    if (option.level(impl.protocol_) == custom_socket_option_level        && option.name(impl.protocol_) == enable_connection_aborted_option)    {      if (option.size(impl.protocol_) != sizeof(int))      {        ec = asio::error::invalid_argument;      }      else      {        int* target = reinterpret_cast<int*>(option.data(impl.protocol_));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -