Add support for sequenced packet sockets (SOCK_SEQPACKET).
This commit is contained in:
parent
39b6482b6b
commit
ed62d29a67
@ -4,6 +4,7 @@ nobase_include_HEADERS = \
|
||||
asio/basic_deadline_timer.hpp \
|
||||
asio/basic_io_object.hpp \
|
||||
asio/basic_raw_socket.hpp \
|
||||
asio/basic_seq_packet_socket.hpp \
|
||||
asio/basic_serial_port.hpp \
|
||||
asio/basic_socket_acceptor.hpp \
|
||||
asio/basic_socket.hpp \
|
||||
@ -128,6 +129,7 @@ nobase_include_HEADERS = \
|
||||
asio/detail/reactive_socket_connect_op.hpp \
|
||||
asio/detail/reactive_socket_recvfrom_op.hpp \
|
||||
asio/detail/reactive_socket_recv_op.hpp \
|
||||
asio/detail/reactive_socket_recvmsg_op.hpp \
|
||||
asio/detail/reactive_socket_send_op.hpp \
|
||||
asio/detail/reactive_socket_sendto_op.hpp \
|
||||
asio/detail/reactive_socket_service_base.hpp \
|
||||
@ -188,6 +190,7 @@ nobase_include_HEADERS = \
|
||||
asio/detail/win_iocp_serial_port_service.hpp \
|
||||
asio/detail/win_iocp_socket_accept_op.hpp \
|
||||
asio/detail/win_iocp_socket_recvfrom_op.hpp \
|
||||
asio/detail/win_iocp_socket_recvmsg_op.hpp \
|
||||
asio/detail/win_iocp_socket_recv_op.hpp \
|
||||
asio/detail/win_iocp_socket_send_op.hpp \
|
||||
asio/detail/win_iocp_socket_service_base.hpp \
|
||||
@ -263,6 +266,7 @@ nobase_include_HEADERS = \
|
||||
asio/read_at.hpp \
|
||||
asio/read.hpp \
|
||||
asio/read_until.hpp \
|
||||
asio/seq_packet_socket_service.hpp \
|
||||
asio/serial_port_base.hpp \
|
||||
asio/serial_port.hpp \
|
||||
asio/serial_port_service.hpp \
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "asio/basic_deadline_timer.hpp"
|
||||
#include "asio/basic_io_object.hpp"
|
||||
#include "asio/basic_raw_socket.hpp"
|
||||
#include "asio/basic_seq_packet_socket.hpp"
|
||||
#include "asio/basic_serial_port.hpp"
|
||||
#include "asio/basic_socket_acceptor.hpp"
|
||||
#include "asio/basic_socket_iostream.hpp"
|
||||
@ -76,6 +77,7 @@
|
||||
#include "asio/read.hpp"
|
||||
#include "asio/read_at.hpp"
|
||||
#include "asio/read_until.hpp"
|
||||
#include "asio/seq_packet_socket_service.hpp"
|
||||
#include "asio/serial_port.hpp"
|
||||
#include "asio/serial_port_base.hpp"
|
||||
#include "asio/serial_port_service.hpp"
|
||||
|
471
asio/include/asio/basic_seq_packet_socket.hpp
Normal file
471
asio/include/asio/basic_seq_packet_socket.hpp
Normal file
@ -0,0 +1,471 @@
|
||||
//
|
||||
// basic_seq_packet_socket.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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_BASIC_SEQ_PACKET_SOCKET_HPP
|
||||
#define ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <cstddef>
|
||||
#include "asio/basic_socket.hpp"
|
||||
#include "asio/detail/handler_type_requirements.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/seq_packet_socket_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Provides sequenced packet socket functionality.
|
||||
/**
|
||||
* The basic_seq_packet_socket class template provides asynchronous and blocking
|
||||
* sequenced packet socket functionality.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename Protocol,
|
||||
typename SeqPacketSocketService = seq_packet_socket_service<Protocol> >
|
||||
class basic_seq_packet_socket
|
||||
: public basic_socket<Protocol, SeqPacketSocketService>
|
||||
{
|
||||
public:
|
||||
/// (Deprecated: Use native_handle_type.) The native representation of a
|
||||
/// socket.
|
||||
typedef typename SeqPacketSocketService::native_handle_type native_type;
|
||||
|
||||
/// The native representation of a socket.
|
||||
typedef typename SeqPacketSocketService::native_handle_type
|
||||
native_handle_type;
|
||||
|
||||
/// The protocol type.
|
||||
typedef Protocol protocol_type;
|
||||
|
||||
/// The endpoint type.
|
||||
typedef typename Protocol::endpoint endpoint_type;
|
||||
|
||||
/// Construct a basic_seq_packet_socket without opening it.
|
||||
/**
|
||||
* This constructor creates a sequenced packet socket without opening it. The
|
||||
* socket needs to be opened and then connected or accepted before data can
|
||||
* be sent or received on it.
|
||||
*
|
||||
* @param io_service The io_service object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
*/
|
||||
explicit basic_seq_packet_socket(asio::io_service& io_service)
|
||||
: basic_socket<Protocol, SeqPacketSocketService>(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct and open a basic_seq_packet_socket.
|
||||
/**
|
||||
* This constructor creates and opens a sequenced_packet socket. The socket
|
||||
* needs to be connected or accepted before data can be sent or received on
|
||||
* it.
|
||||
*
|
||||
* @param io_service The io_service object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_seq_packet_socket(asio::io_service& io_service,
|
||||
const protocol_type& protocol)
|
||||
: basic_socket<Protocol, SeqPacketSocketService>(io_service, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_seq_packet_socket, opening it and binding it to the
|
||||
/// given local endpoint.
|
||||
/**
|
||||
* This constructor creates a sequenced packet socket and automatically opens
|
||||
* it bound to the specified endpoint on the local machine. The protocol used
|
||||
* is the protocol associated with the given endpoint.
|
||||
*
|
||||
* @param io_service The io_service object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the sequenced
|
||||
* packet socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_seq_packet_socket(asio::io_service& io_service,
|
||||
const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol, SeqPacketSocketService>(io_service, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_seq_packet_socket on an existing native socket.
|
||||
/**
|
||||
* This constructor creates a sequenced packet socket object to hold an
|
||||
* existing native socket.
|
||||
*
|
||||
* @param io_service The io_service object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @param native_socket The new underlying socket implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_seq_packet_socket(asio::io_service& io_service,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket)
|
||||
: basic_socket<Protocol, SeqPacketSocketService>(
|
||||
io_service, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
/// Send some data on the socket.
|
||||
/**
|
||||
* This function is used to send data on the sequenced packet socket. The
|
||||
* function call will block until the data has been sent successfully, or an
|
||||
* until error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be sent on the socket.
|
||||
*
|
||||
* @param flags Flags specifying how the send call is to be made.
|
||||
*
|
||||
* @returns The number of bytes sent.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @par Example
|
||||
* To send a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* socket.send(asio::buffer(data, size), 0);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on sending multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t send(const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->service.send(
|
||||
this->implementation, buffers, flags, ec);
|
||||
asio::detail::throw_error(ec);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Send some data on the socket.
|
||||
/**
|
||||
* This function is used to send data on the sequenced packet socket. The
|
||||
* function call will block the data has been sent successfully, or an until
|
||||
* error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be sent on the socket.
|
||||
*
|
||||
* @param flags Flags specifying how the send call is to be made.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes sent. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The send operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref write function if you need to ensure that all data
|
||||
* is written before the blocking operation completes.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t send(const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, asio::error_code& ec)
|
||||
{
|
||||
return this->service.send(this->implementation, buffers, flags, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous send.
|
||||
/**
|
||||
* This function is used to asynchronously send data on the sequenced packet
|
||||
* socket. The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more data buffers to be sent on the socket. Although
|
||||
* the buffers object may be copied as necessary, ownership of the underlying
|
||||
* memory blocks is retained by the caller, which must guarantee that they
|
||||
* remain valid until the handler is called.
|
||||
*
|
||||
* @param flags Flags specifying how the send call is to be made.
|
||||
*
|
||||
* @param handler The handler to be called when the send operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_service::post().
|
||||
*
|
||||
* @par Example
|
||||
* To send a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* socket.async_send(asio::buffer(data, size), 0, handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on sending multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
void async_send(const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, WriteHandler handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a WriteHandler.
|
||||
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||
|
||||
this->service.async_send(this->implementation, buffers, flags,
|
||||
ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||
}
|
||||
|
||||
/// Receive some data on the socket.
|
||||
/**
|
||||
* This function is used to receive data on the sequenced packet socket. The
|
||||
* function call will block until data has been received successfully, or
|
||||
* until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be received.
|
||||
*
|
||||
* @param out_flags After the receive call completes, contains flags
|
||||
* associated with the received data. For example, if the
|
||||
* socket_base::message_end_of_record bit is set then the received data marks
|
||||
* the end of a record.
|
||||
*
|
||||
* @returns The number of bytes received.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
* follows:
|
||||
* @code
|
||||
* socket.receive(asio::buffer(data, size), out_flags);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on receiving into
|
||||
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t receive(const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags& out_flags)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->service.receive(
|
||||
this->implementation, buffers, 0, out_flags, ec);
|
||||
asio::detail::throw_error(ec);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Receive some data on the socket.
|
||||
/**
|
||||
* This function is used to receive data on the sequenced packet socket. The
|
||||
* function call will block until data has been received successfully, or
|
||||
* until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be received.
|
||||
*
|
||||
* @param in_flags Flags specifying how the receive call is to be made.
|
||||
*
|
||||
* @param out_flags After the receive call completes, contains flags
|
||||
* associated with the received data. For example, if the
|
||||
* socket_base::message_end_of_record bit is set then the received data marks
|
||||
* the end of a record.
|
||||
*
|
||||
* @returns The number of bytes received.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The receive operation may not receive all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that the
|
||||
* requested amount of data is read before the blocking operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
* follows:
|
||||
* @code
|
||||
* socket.receive(asio::buffer(data, size), 0, out_flags);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on receiving into
|
||||
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t receive(const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->service.receive(
|
||||
this->implementation, buffers, in_flags, out_flags, ec);
|
||||
asio::detail::throw_error(ec);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Receive some data on a connected socket.
|
||||
/**
|
||||
* This function is used to receive data on the sequenced packet socket. The
|
||||
* function call will block until data has been received successfully, or
|
||||
* until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be received.
|
||||
*
|
||||
* @param in_flags Flags specifying how the receive call is to be made.
|
||||
*
|
||||
* @param out_flags After the receive call completes, contains flags
|
||||
* associated with the received data. For example, if the
|
||||
* socket_base::message_end_of_record bit is set then the received data marks
|
||||
* the end of a record.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes received. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The receive operation may not receive all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that the
|
||||
* requested amount of data is read before the blocking operation completes.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t receive(const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, asio::error_code& ec)
|
||||
{
|
||||
return this->service.receive(this->implementation,
|
||||
buffers, in_flags, out_flags, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive.
|
||||
/**
|
||||
* This function is used to asynchronously receive data from the sequenced
|
||||
* packet socket. The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be received.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param out_flags Once the asynchronous operation completes, contains flags
|
||||
* associated with the received data. For example, if the
|
||||
* socket_base::message_end_of_record bit is set then the received data marks
|
||||
* the end of a record. The caller must guarantee that the referenced
|
||||
* variable remains valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the receive operation
|
||||
* completes. Copies will be made of the handler as required. The function
|
||||
* signature of the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_service::post().
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
* follows:
|
||||
* @code
|
||||
* socket.async_receive(asio::buffer(data, size), out_flags, handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on receiving into
|
||||
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
void async_receive(const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags& out_flags, ReadHandler handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a ReadHandler.
|
||||
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||
|
||||
this->service.async_receive(this->implementation, buffers,
|
||||
0, out_flags, ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive.
|
||||
/**
|
||||
* This function is used to asynchronously receive data from the sequenced
|
||||
* data socket. The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be received.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param in_flags Flags specifying how the receive call is to be made.
|
||||
*
|
||||
* @param out_flags Once the asynchronous operation completes, contains flags
|
||||
* associated with the received data. For example, if the
|
||||
* socket_base::message_end_of_record bit is set then the received data marks
|
||||
* the end of a record. The caller must guarantee that the referenced
|
||||
* variable remains valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the receive operation
|
||||
* completes. Copies will be made of the handler as required. The function
|
||||
* signature of the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_service::post().
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
* follows:
|
||||
* @code
|
||||
* socket.async_receive(
|
||||
* asio::buffer(data, size),
|
||||
* 0, out_flags, handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on receiving into
|
||||
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
void async_receive(const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, ReadHandler handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a ReadHandler.
|
||||
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||
|
||||
this->service.async_receive(this->implementation, buffers,
|
||||
in_flags, out_flags, ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
|
@ -919,6 +919,116 @@ bool non_blocking_recvfrom(socket_type s,
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
int recvmsg(socket_type s, buf* bufs, size_t count,
|
||||
int in_flags, int& out_flags, asio::error_code& ec)
|
||||
{
|
||||
clear_last_error();
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
out_flags = 0;
|
||||
return socket_ops::recv(s, bufs, count, in_flags, ec);
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
int result = error_wrapper(::recvmsg(s, &msg, in_flags), ec);
|
||||
if (result >= 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
out_flags = msg.msg_flags;
|
||||
}
|
||||
else
|
||||
out_flags = 0;
|
||||
return result;
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
size_t sync_recvmsg(socket_type s, state_type state,
|
||||
buf* bufs, size_t count, int in_flags, int& out_flags,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (s == invalid_socket)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
int bytes = socket_ops::recvmsg(s, bufs, count, in_flags, out_flags, ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
return bytes;
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != asio::error::would_block
|
||||
&& ec != asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for socket to become ready.
|
||||
if (socket_ops::poll_read(s, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
void complete_iocp_recvmsg(
|
||||
const weak_cancel_token_type& cancel_token,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
// Map non-portable errors to their portable counterparts.
|
||||
if (ec.value() == ERROR_NETNAME_DELETED)
|
||||
{
|
||||
if (cancel_token.expired())
|
||||
ec = asio::error::operation_aborted;
|
||||
else
|
||||
ec = asio::error::connection_reset;
|
||||
}
|
||||
else if (ec.value() == ERROR_PORT_UNREACHABLE)
|
||||
{
|
||||
ec = asio::error::connection_refused;
|
||||
}
|
||||
}
|
||||
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
|
||||
bool non_blocking_recvmsg(socket_type s,
|
||||
buf* bufs, size_t count, int in_flags, int& out_flags,
|
||||
asio::error_code& ec, size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
int bytes = socket_ops::recvmsg(s, bufs, count, in_flags, out_flags, ec);
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == asio::error::would_block
|
||||
|| ec == asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation is complete.
|
||||
if (bytes >= 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
bytes_transferred = bytes;
|
||||
}
|
||||
else
|
||||
bytes_transferred = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
int send(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
|
120
asio/include/asio/detail/reactive_socket_recvmsg_op.hpp
Normal file
120
asio/include/asio/detail/reactive_socket_recvmsg_op.hpp
Normal file
@ -0,0 +1,120 @@
|
||||
//
|
||||
// detail/reactive_socket_recvmsg_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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_RECVMSG_OP_HPP
|
||||
#define ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/reactor_op.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
class reactive_socket_recvmsg_op_base : public reactor_op
|
||||
{
|
||||
public:
|
||||
reactive_socket_recvmsg_op_base(socket_type socket,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, func_type complete_func)
|
||||
: reactor_op(&reactive_socket_recvmsg_op_base::do_perform, complete_func),
|
||||
socket_(socket),
|
||||
buffers_(buffers),
|
||||
in_flags_(in_flags),
|
||||
out_flags_(out_flags)
|
||||
{
|
||||
}
|
||||
|
||||
static bool do_perform(reactor_op* base)
|
||||
{
|
||||
reactive_socket_recvmsg_op_base* o(
|
||||
static_cast<reactive_socket_recvmsg_op_base*>(base));
|
||||
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
MutableBufferSequence> bufs(o->buffers_);
|
||||
|
||||
return socket_ops::non_blocking_recvmsg(o->socket_,
|
||||
bufs.buffers(), bufs.count(),
|
||||
o->in_flags_, o->out_flags_,
|
||||
o->ec_, o->bytes_transferred_);
|
||||
}
|
||||
|
||||
private:
|
||||
socket_type socket_;
|
||||
MutableBufferSequence buffers_;
|
||||
socket_base::message_flags in_flags_;
|
||||
socket_base::message_flags& out_flags_;
|
||||
};
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
class reactive_socket_recvmsg_op :
|
||||
public reactive_socket_recvmsg_op_base<MutableBufferSequence>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op);
|
||||
|
||||
reactive_socket_recvmsg_op(socket_type socket,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
: reactive_socket_recvmsg_op_base<MutableBufferSequence>(socket, buffers,
|
||||
in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
static void do_complete(io_service_impl* owner, operation* base,
|
||||
asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
reactive_socket_recvmsg_op* o(
|
||||
static_cast<reactive_socket_recvmsg_op*>(base));
|
||||
ptr p = { boost::addressof(o->handler_), o, o };
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
// with the handler. Consequently, a local copy of the handler is required
|
||||
// to ensure that any owning sub-object remains valid until after we have
|
||||
// deallocated the memory here.
|
||||
detail::binder2<Handler, asio::error_code, std::size_t>
|
||||
handler(o->handler_, o->ec_, o->bytes_transferred_);
|
||||
p.h = boost::addressof(handler.handler_);
|
||||
p.reset();
|
||||
|
||||
// Make the upcall if required.
|
||||
if (owner)
|
||||
{
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler.handler_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
|
@ -27,6 +27,7 @@
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/reactive_null_buffers_op.hpp"
|
||||
#include "asio/detail/reactive_socket_recv_op.hpp"
|
||||
#include "asio/detail/reactive_socket_recvmsg_op.hpp"
|
||||
#include "asio/detail/reactive_socket_send_op.hpp"
|
||||
#include "asio/detail/reactor.hpp"
|
||||
#include "asio/detail/reactor_op.hpp"
|
||||
@ -285,6 +286,81 @@ public:
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
// Receive some data with associated flags. Returns the number of bytes
|
||||
// received.
|
||||
template <typename MutableBufferSequence>
|
||||
size_t receive_with_flags(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, asio::error_code& ec)
|
||||
{
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
MutableBufferSequence> bufs(buffers);
|
||||
|
||||
return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
|
||||
bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
size_t receive_with_flags(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags,
|
||||
socket_base::message_flags& out_flags, asio::error_code& ec)
|
||||
{
|
||||
// Wait for socket to become ready.
|
||||
socket_ops::poll_read(impl.socket_, ec);
|
||||
|
||||
// Clear out_flags, since we cannot give it any other sensible value when
|
||||
// performing a null_buffers operation.
|
||||
out_flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
|
||||
|
||||
start_op(impl,
|
||||
(in_flags & socket_base::message_out_of_band)
|
||||
? reactor::except_op : reactor::read_op,
|
||||
p.p, (in_flags & socket_base::message_out_of_band) == 0, false);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
|
||||
// Clear out_flags, since we cannot give it any other sensible value when
|
||||
// performing a null_buffers operation.
|
||||
out_flags = 0;
|
||||
|
||||
start_op(impl,
|
||||
(in_flags & socket_base::message_out_of_band)
|
||||
? reactor::except_op : reactor::read_op,
|
||||
p.p, false, false);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Open a new socket implementation.
|
||||
ASIO_DECL asio::error_code do_open(
|
||||
|
@ -168,6 +168,27 @@ ASIO_DECL bool non_blocking_recvfrom(socket_type s,
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
ASIO_DECL int recvmsg(socket_type s, buf* bufs, size_t count,
|
||||
int in_flags, int& out_flags, asio::error_code& ec);
|
||||
|
||||
ASIO_DECL size_t sync_recvmsg(socket_type s, state_type state,
|
||||
buf* bufs, size_t count, int in_flags, int& out_flags,
|
||||
asio::error_code& ec);
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
ASIO_DECL void complete_iocp_recvmsg(
|
||||
const weak_cancel_token_type& cancel_token,
|
||||
asio::error_code& ec);
|
||||
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
|
||||
ASIO_DECL bool non_blocking_recvmsg(socket_type s,
|
||||
buf* bufs, size_t count, int in_flags, int& out_flags,
|
||||
asio::error_code& ec, size_t& bytes_transferred);
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
ASIO_DECL int send(socket_type s, const buf* bufs,
|
||||
size_t count, int flags, asio::error_code& ec);
|
||||
|
||||
|
@ -112,6 +112,7 @@ const int shutdown_both = SD_BOTH;
|
||||
const int message_peek = MSG_PEEK;
|
||||
const int message_out_of_band = MSG_OOB;
|
||||
const int message_do_not_route = MSG_DONTROUTE;
|
||||
const int message_end_of_record = 0; // Not supported on Windows.
|
||||
# if defined (_WIN32_WINNT)
|
||||
const int max_iov_len = 64;
|
||||
# else
|
||||
@ -155,6 +156,7 @@ const int shutdown_both = SHUT_RDWR;
|
||||
const int message_peek = MSG_PEEK;
|
||||
const int message_out_of_band = MSG_OOB;
|
||||
const int message_do_not_route = MSG_DONTROUTE;
|
||||
const int message_end_of_record = MSG_EOR;
|
||||
# if defined(IOV_MAX)
|
||||
const int max_iov_len = IOV_MAX;
|
||||
# else
|
||||
|
109
asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp
Normal file
109
asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp
Normal file
@ -0,0 +1,109 @@
|
||||
//
|
||||
// detail/win_iocp_socket_recvmsg_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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_WIN_IOCP_SOCKET_RECVMSG_OP_HPP
|
||||
#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/operation.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
class win_iocp_socket_recvmsg_op : public operation
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recvmsg_op);
|
||||
|
||||
win_iocp_socket_recvmsg_op(
|
||||
socket_ops::weak_cancel_token_type cancel_token,
|
||||
const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
: operation(&win_iocp_socket_recvmsg_op::do_complete),
|
||||
cancel_token_(cancel_token),
|
||||
buffers_(buffers),
|
||||
out_flags_(out_flags),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
static void do_complete(io_service_impl* owner, operation* base,
|
||||
asio::error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_socket_recvmsg_op* o(
|
||||
static_cast<win_iocp_socket_recvmsg_op*>(base));
|
||||
ptr p = { boost::addressof(o->handler_), o, o };
|
||||
|
||||
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
|
||||
// Check whether buffers are still valid.
|
||||
if (owner)
|
||||
{
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
MutableBufferSequence>::validate(o->buffers_);
|
||||
}
|
||||
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
|
||||
|
||||
socket_ops::complete_iocp_recvmsg(o->cancel_token_, ec);
|
||||
o->out_flags_ = 0;
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
// with the handler. Consequently, a local copy of the handler is required
|
||||
// to ensure that any owning sub-object remains valid until after we have
|
||||
// deallocated the memory here.
|
||||
detail::binder2<Handler, asio::error_code, std::size_t>
|
||||
handler(o->handler_, ec, bytes_transferred);
|
||||
p.h = boost::addressof(handler.handler_);
|
||||
p.reset();
|
||||
|
||||
// Make the upcall if required.
|
||||
if (owner)
|
||||
{
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler.handler_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
MutableBufferSequence buffers_;
|
||||
socket_base::message_flags& out_flags_;
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_HPP
|
@ -40,6 +40,7 @@
|
||||
#include "asio/detail/win_iocp_null_buffers_op.hpp"
|
||||
#include "asio/detail/win_iocp_socket_send_op.hpp"
|
||||
#include "asio/detail/win_iocp_socket_recv_op.hpp"
|
||||
#include "asio/detail/win_iocp_socket_recvmsg_op.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
@ -301,6 +302,77 @@ public:
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
// Receive some data with associated flags. Returns the number of bytes
|
||||
// received.
|
||||
template <typename MutableBufferSequence>
|
||||
size_t receive_with_flags(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, asio::error_code& ec)
|
||||
{
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
MutableBufferSequence> bufs(buffers);
|
||||
|
||||
return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
|
||||
bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
size_t receive_with_flags(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags,
|
||||
socket_base::message_flags& out_flags, asio::error_code& ec)
|
||||
{
|
||||
// Wait for socket to become ready.
|
||||
socket_ops::poll_read(impl.socket_, ec);
|
||||
|
||||
// Clear out_flags, since we cannot give it any other sensible value when
|
||||
// performing a null_buffers operation.
|
||||
out_flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_recvmsg_op<MutableBufferSequence, Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler);
|
||||
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
MutableBufferSequence> bufs(buffers);
|
||||
|
||||
start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, p.p);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_null_buffers_op<Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler);
|
||||
|
||||
// Reset out_flags since it can be given no sensible value at this time.
|
||||
out_flags = 0;
|
||||
|
||||
start_null_buffers_receive_op(impl, in_flags, p.p);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
// Helper function to restart an asynchronous accept operation.
|
||||
ASIO_DECL void restart_accept_op(socket_type s,
|
||||
socket_holder& new_socket, int family, int type, int protocol,
|
||||
|
317
asio/include/asio/seq_packet_socket_service.hpp
Normal file
317
asio/include/asio/seq_packet_socket_service.hpp
Normal file
@ -0,0 +1,317 @@
|
||||
//
|
||||
// seq_packet_socket_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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_SEQ_PACKET_SOCKET_SERVICE_HPP
|
||||
#define ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <cstddef>
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_service.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_socket_service.hpp"
|
||||
#else
|
||||
# include "asio/detail/reactive_socket_service.hpp"
|
||||
#endif
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Default service implementation for a sequenced packet socket.
|
||||
template <typename Protocol>
|
||||
class seq_packet_socket_service
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
: public asio::io_service::service
|
||||
#else
|
||||
: public asio::detail::service_base<
|
||||
seq_packet_socket_service<Protocol> >
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
/// The unique service identifier.
|
||||
static asio::io_service::id id;
|
||||
#endif
|
||||
|
||||
/// The protocol type.
|
||||
typedef Protocol protocol_type;
|
||||
|
||||
/// The endpoint type.
|
||||
typedef typename Protocol::endpoint endpoint_type;
|
||||
|
||||
private:
|
||||
// The type of the platform-specific implementation.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
|
||||
#else
|
||||
typedef detail::reactive_socket_service<Protocol> service_impl_type;
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// The type of a sequenced packet socket implementation.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined implementation_type;
|
||||
#else
|
||||
typedef typename service_impl_type::implementation_type implementation_type;
|
||||
#endif
|
||||
|
||||
/// (Deprecated: Use native_handle_type.) The native socket type.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_type;
|
||||
#else
|
||||
typedef typename service_impl_type::native_handle_type native_type;
|
||||
#endif
|
||||
|
||||
/// The native socket type.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#else
|
||||
typedef typename service_impl_type::native_handle_type native_handle_type;
|
||||
#endif
|
||||
|
||||
/// Construct a new sequenced packet socket service for the specified
|
||||
/// io_service.
|
||||
explicit seq_packet_socket_service(asio::io_service& io_service)
|
||||
: asio::detail::service_base<
|
||||
seq_packet_socket_service<Protocol> >(io_service),
|
||||
service_impl_(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destroy all user-defined handler objects owned by the service.
|
||||
void shutdown_service()
|
||||
{
|
||||
service_impl_.shutdown_service();
|
||||
}
|
||||
|
||||
/// Construct a new sequenced packet socket implementation.
|
||||
void construct(implementation_type& impl)
|
||||
{
|
||||
service_impl_.construct(impl);
|
||||
}
|
||||
|
||||
/// Destroy a sequenced packet socket implementation.
|
||||
void destroy(implementation_type& impl)
|
||||
{
|
||||
service_impl_.destroy(impl);
|
||||
}
|
||||
|
||||
/// Open a sequenced packet socket.
|
||||
asio::error_code open(implementation_type& impl,
|
||||
const protocol_type& protocol, asio::error_code& ec)
|
||||
{
|
||||
if (protocol.type() == SOCK_SEQPACKET)
|
||||
service_impl_.open(impl, protocol, ec);
|
||||
else
|
||||
ec = asio::error::invalid_argument;
|
||||
return ec;
|
||||
}
|
||||
|
||||
/// Assign an existing native socket to a sequenced packet socket.
|
||||
asio::error_code assign(implementation_type& impl,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.assign(impl, protocol, native_socket, ec);
|
||||
}
|
||||
|
||||
/// Determine whether the socket is open.
|
||||
bool is_open(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.is_open(impl);
|
||||
}
|
||||
|
||||
/// Close a sequenced packet socket implementation.
|
||||
asio::error_code close(implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.close(impl, ec);
|
||||
}
|
||||
|
||||
/// (Deprecated: Use native_handle().) Get the native socket implementation.
|
||||
native_type native(implementation_type& impl)
|
||||
{
|
||||
return service_impl_.native_handle(impl);
|
||||
}
|
||||
|
||||
/// Get the native socket implementation.
|
||||
native_handle_type native_handle(implementation_type& impl)
|
||||
{
|
||||
return service_impl_.native_handle(impl);
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the socket.
|
||||
asio::error_code cancel(implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.cancel(impl, 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
|
||||
{
|
||||
return service_impl_.at_mark(impl, ec);
|
||||
}
|
||||
|
||||
/// Determine the number of bytes available for reading.
|
||||
std::size_t available(const implementation_type& impl,
|
||||
asio::error_code& ec) const
|
||||
{
|
||||
return service_impl_.available(impl, ec);
|
||||
}
|
||||
|
||||
/// Bind the sequenced packet socket to the specified local endpoint.
|
||||
asio::error_code bind(implementation_type& impl,
|
||||
const endpoint_type& endpoint, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.bind(impl, endpoint, ec);
|
||||
}
|
||||
|
||||
/// Connect the sequenced packet socket to the specified endpoint.
|
||||
asio::error_code connect(implementation_type& impl,
|
||||
const endpoint_type& peer_endpoint, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.connect(impl, peer_endpoint, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous connect.
|
||||
template <typename ConnectHandler>
|
||||
void async_connect(implementation_type& impl,
|
||||
const endpoint_type& peer_endpoint, ConnectHandler handler)
|
||||
{
|
||||
service_impl_.async_connect(impl, peer_endpoint, handler);
|
||||
}
|
||||
|
||||
/// Set a socket option.
|
||||
template <typename SettableSocketOption>
|
||||
asio::error_code set_option(implementation_type& impl,
|
||||
const SettableSocketOption& option, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.set_option(impl, option, ec);
|
||||
}
|
||||
|
||||
/// Get a socket option.
|
||||
template <typename GettableSocketOption>
|
||||
asio::error_code get_option(const implementation_type& impl,
|
||||
GettableSocketOption& option, asio::error_code& ec) const
|
||||
{
|
||||
return service_impl_.get_option(impl, option, ec);
|
||||
}
|
||||
|
||||
/// Perform an IO control command on the socket.
|
||||
template <typename IoControlCommand>
|
||||
asio::error_code io_control(implementation_type& impl,
|
||||
IoControlCommand& command, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.io_control(impl, command, ec);
|
||||
}
|
||||
|
||||
/// Gets the non-blocking mode of the socket.
|
||||
bool non_blocking(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.non_blocking(impl);
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the socket.
|
||||
asio::error_code non_blocking(implementation_type& impl,
|
||||
bool mode, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.non_blocking(impl, mode, ec);
|
||||
}
|
||||
|
||||
/// Gets the non-blocking mode of the native socket implementation.
|
||||
bool native_non_blocking(const implementation_type& impl) const
|
||||
{
|
||||
return service_impl_.native_non_blocking(impl);
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the native socket implementation.
|
||||
asio::error_code native_non_blocking(implementation_type& impl,
|
||||
bool mode, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.native_non_blocking(impl, mode, ec);
|
||||
}
|
||||
|
||||
/// Get the local endpoint.
|
||||
endpoint_type local_endpoint(const implementation_type& impl,
|
||||
asio::error_code& ec) const
|
||||
{
|
||||
return service_impl_.local_endpoint(impl, ec);
|
||||
}
|
||||
|
||||
/// Get the remote endpoint.
|
||||
endpoint_type remote_endpoint(const implementation_type& impl,
|
||||
asio::error_code& ec) const
|
||||
{
|
||||
return service_impl_.remote_endpoint(impl, ec);
|
||||
}
|
||||
|
||||
/// Disable sends or receives on the socket.
|
||||
asio::error_code shutdown(implementation_type& impl,
|
||||
socket_base::shutdown_type what, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.shutdown(impl, what, ec);
|
||||
}
|
||||
|
||||
/// Send the given data to the peer.
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t send(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.send(impl, buffers, flags, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous send.
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
void async_send(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, WriteHandler handler)
|
||||
{
|
||||
service_impl_.async_send(impl, buffers, flags, handler);
|
||||
}
|
||||
|
||||
/// Receive some data from the peer.
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t receive(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, asio::error_code& ec)
|
||||
{
|
||||
return service_impl_.receive_with_flags(impl,
|
||||
buffers, in_flags, out_flags, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous receive.
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
void async_receive(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, ReadHandler handler)
|
||||
{
|
||||
service_impl_.async_receive_with_flags(impl,
|
||||
buffers, in_flags, out_flags, handler);
|
||||
}
|
||||
|
||||
private:
|
||||
// The platform-specific implementation.
|
||||
service_impl_type service_impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP
|
@ -62,6 +62,9 @@ public:
|
||||
|
||||
/// Specify that the data should not be subject to routing.
|
||||
static const int message_do_not_route = implementation_defined;
|
||||
|
||||
/// Specifies that the data marks the end of a record.
|
||||
static const int message_end_of_record = implementation_defined;
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(int,
|
||||
message_peek = asio::detail::message_peek);
|
||||
@ -69,6 +72,8 @@ public:
|
||||
message_out_of_band = asio::detail::message_out_of_band);
|
||||
BOOST_STATIC_CONSTANT(int,
|
||||
message_do_not_route = asio::detail::message_do_not_route);
|
||||
BOOST_STATIC_CONSTANT(int,
|
||||
message_end_of_record = asio::detail::message_end_of_record);
|
||||
#endif
|
||||
|
||||
/// Socket option to permit sending of broadcast messages.
|
||||
|
@ -14,6 +14,7 @@ check_PROGRAMS = \
|
||||
tests/unit/basic_datagram_socket \
|
||||
tests/unit/basic_deadline_timer \
|
||||
tests/unit/basic_raw_socket \
|
||||
tests/unit/basic_seq_packet_socket \
|
||||
tests/unit/basic_serial_port \
|
||||
tests/unit/basic_socket_acceptor \
|
||||
tests/unit/basic_stream_socket \
|
||||
@ -61,6 +62,7 @@ check_PROGRAMS = \
|
||||
tests/unit/read \
|
||||
tests/unit/read_at \
|
||||
tests/unit/read_until \
|
||||
tests/unit/seq_packet_socket_service \
|
||||
tests/unit/serial_port \
|
||||
tests/unit/serial_port_base \
|
||||
tests/unit/serial_port_service \
|
||||
@ -169,6 +171,7 @@ TESTS = \
|
||||
tests/unit/basic_datagram_socket \
|
||||
tests/unit/basic_deadline_timer \
|
||||
tests/unit/basic_raw_socket \
|
||||
tests/unit/basic_seq_packet_socket \
|
||||
tests/unit/basic_serial_port \
|
||||
tests/unit/basic_socket_acceptor \
|
||||
tests/unit/basic_stream_socket \
|
||||
@ -216,6 +219,7 @@ TESTS = \
|
||||
tests/unit/read \
|
||||
tests/unit/read_at \
|
||||
tests/unit/read_until \
|
||||
tests/unit/seq_packet_socket_service \
|
||||
tests/unit/serial_port \
|
||||
tests/unit/serial_port_base \
|
||||
tests/unit/serial_port_service \
|
||||
@ -272,6 +276,7 @@ tests_performance_server_SOURCES = tests/performance/server.cpp
|
||||
tests_unit_basic_datagram_socket_SOURCES = tests/unit/basic_datagram_socket.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_basic_deadline_timer_SOURCES = tests/unit/basic_deadline_timer.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_basic_raw_socket_SOURCES = tests/unit/basic_raw_socket.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_basic_seq_packet_socket_SOURCES = tests/unit/basic_seq_packet_socket.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_basic_serial_port_SOURCES = tests/unit/basic_serial_port.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_basic_socket_acceptor_SOURCES = tests/unit/basic_socket_acceptor.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_basic_stream_socket_SOURCES = tests/unit/basic_stream_socket.cpp tests/unit/unit_test.cpp
|
||||
@ -319,6 +324,7 @@ tests_unit_raw_socket_service_SOURCES = tests/unit/raw_socket_service.cpp tests/
|
||||
tests_unit_read_SOURCES = tests/unit/read.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_read_at_SOURCES = tests/unit/read_at.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_read_until_SOURCES = tests/unit/read_until.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_seq_packet_socket_service_SOURCES = tests/unit/seq_packet_socket_service.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_serial_port_SOURCES = tests/unit/serial_port.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_serial_port_base_SOURCES = tests/unit/serial_port_base.cpp tests/unit/unit_test.cpp
|
||||
tests_unit_serial_port_service_SOURCES = tests/unit/serial_port_service.cpp tests/unit/unit_test.cpp
|
||||
|
@ -17,6 +17,7 @@ UNIT_TEST_EXES = \
|
||||
tests/unit/basic_datagram_socket.exe \
|
||||
tests/unit/basic_deadline_timer.exe \
|
||||
tests/unit/basic_raw_socket.exe \
|
||||
tests/unit/basic_seq_packet_socket.exe \
|
||||
tests/unit/basic_serial_port.exe \
|
||||
tests/unit/basic_socket_acceptor.exe \
|
||||
tests/unit/basic_stream_socket.exe \
|
||||
@ -55,6 +56,7 @@ UNIT_TEST_EXES = \
|
||||
tests/unit/read.exe \
|
||||
tests/unit/read_at.exe \
|
||||
tests/unit/read_until.exe \
|
||||
tests/unit/seq_packet_socket_service.exe \
|
||||
tests/unit/serial_port.exe \
|
||||
tests/unit/serial_port_base.exe \
|
||||
tests/unit/serial_port_service.exe \
|
||||
|
@ -82,6 +82,7 @@ UNIT_TEST_EXES = \
|
||||
tests\unit\basic_datagram_socket.exe \
|
||||
tests\unit\basic_deadline_timer.exe \
|
||||
tests\unit\basic_raw_socket.exe \
|
||||
tests\unit\basic_seq_packet_socket.exe \
|
||||
tests\unit\basic_serial_port.exe \
|
||||
tests\unit\basic_socket_acceptor.exe \
|
||||
tests\unit\basic_stream_socket.exe \
|
||||
@ -120,6 +121,7 @@ UNIT_TEST_EXES = \
|
||||
tests\unit\read.exe \
|
||||
tests\unit\read_at.exe \
|
||||
tests\unit\read_until.exe \
|
||||
tests\unit\seq_packet_socket_service.exe \
|
||||
tests\unit\serial_port.exe \
|
||||
tests\unit\serial_port_base.exe \
|
||||
tests\unit\serial_port_service.exe \
|
||||
|
2
asio/src/tests/unit/.gitignore
vendored
2
asio/src/tests/unit/.gitignore
vendored
@ -10,6 +10,7 @@
|
||||
basic_datagram_socket
|
||||
basic_deadline_timer
|
||||
basic_raw_socket
|
||||
basic_seq_packet_socket
|
||||
basic_serial_port
|
||||
basic_socket_acceptor
|
||||
basic_stream_socket
|
||||
@ -33,6 +34,7 @@ raw_socket_service
|
||||
read
|
||||
read_at
|
||||
read_until
|
||||
seq_packet_socket_service
|
||||
serial_port
|
||||
serial_port_base
|
||||
serial_port_service
|
||||
|
26
asio/src/tests/unit/basic_seq_packet_socket.cpp
Normal file
26
asio/src/tests/unit/basic_seq_packet_socket.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// basic_seq_packet_socket.cpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "asio/basic_seq_packet_socket.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("basic_seq_packet_socket");
|
||||
test->add(BOOST_TEST_CASE(&null_test));
|
||||
return test;
|
||||
}
|
26
asio/src/tests/unit/seq_packet_socket_service.cpp
Normal file
26
asio/src/tests/unit/seq_packet_socket_service.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// seq_packet_socket_service.cpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "asio/seq_packet_socket_service.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("seq_packet_socket_service");
|
||||
test->add(BOOST_TEST_CASE(&null_test));
|
||||
return test;
|
||||
}
|
Loading…
Reference in New Issue
Block a user