--- boost/asio/detail/impl/socket_ops.ipp.orig 2010-10-22 15:47:03.707774284 -0400 +++ boost/asio/detail/impl/socket_ops.ipp 2010-10-25 19:59:15.462589058 -0400 @@ -741,6 +741,7 @@ int recvfrom(socket_type s, buf* bufs, size_t count, int flags, socket_addr_type* addr, std::size_t* addrlen, + void* control, std::size_t controllen, boost::system::error_code& ec) { clear_last_error(); @@ -767,6 +768,10 @@ msg.msg_namelen = *addrlen; msg.msg_iov = bufs; msg.msg_iovlen = count; + if (controllen > 0) { + msg.msg_control = control; + msg.msg_controllen = controllen; + } int result = error_wrapper(::recvmsg(s, &msg, flags), ec); *addrlen = msg.msg_namelen; if (result >= 0) @@ -777,7 +782,9 @@ size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, size_t count, int flags, socket_addr_type* addr, - std::size_t* addrlen, boost::system::error_code& ec) + std::size_t* addrlen, + void* control, std::size_t controllen, + boost::system::error_code& ec) { if (s == invalid_socket) { @@ -789,7 +796,8 @@ for (;;) { // Try to complete the operation without blocking. - int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, ec); + int bytes = socket_ops::recvfrom(s, bufs, count, + flags, addr, addrlen, control, controllen, ec); // Check if operation succeeded. if (bytes >= 0) @@ -832,12 +840,13 @@ bool non_blocking_recvfrom(socket_type s, buf* bufs, size_t count, int flags, socket_addr_type* addr, std::size_t* addrlen, + void* control, std::size_t controllen, boost::system::error_code& ec, size_t& bytes_transferred) { for (;;) { // Read some data. - int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, ec); + int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, control, controllen, ec); // Retry operation if interrupted by signal. if (ec == boost::asio::error::interrupted) --- boost/asio/detail/win_iocp_socket_service.hpp.orig 2010-10-22 16:09:02.263634298 -0400 +++ boost/asio/detail/win_iocp_socket_service.hpp 2010-10-22 16:09:17.535112065 -0400 @@ -306,7 +306,7 @@ std::size_t addr_len = sender_endpoint.capacity(); std::size_t bytes_recvd = socket_ops::sync_recvfrom( impl.socket_, impl.state_, bufs.buffers(), bufs.count(), - flags, sender_endpoint.data(), &addr_len, ec); + flags, sender_endpoint.data(), &addr_len, NULL, 0, ec); if (!ec) sender_endpoint.resize(addr_len); --- boost/asio/detail/reactive_socket_service.hpp.orig 2010-10-22 15:47:26.029334719 -0400 +++ boost/asio/detail/reactive_socket_service.hpp 2010-10-22 15:48:42.529946860 -0400 @@ -238,7 +238,9 @@ std::size_t addr_len = sender_endpoint.capacity(); std::size_t bytes_recvd = socket_ops::sync_recvfrom( impl.socket_, impl.state_, bufs.buffers(), bufs.count(), - flags, sender_endpoint.data(), &addr_len, ec); + flags, sender_endpoint.data(), &addr_len, + sender_endpoint.control(), sender_endpoint.control_size(), + ec); if (!ec) sender_endpoint.resize(addr_len); --- boost/asio/detail/socket_ops.hpp.orig 2010-10-22 16:04:06.559471958 -0400 +++ boost/asio/detail/socket_ops.hpp 2010-10-25 20:00:06.596081467 -0400 @@ -145,11 +145,13 @@ BOOST_ASIO_DECL int recvfrom(socket_type s, buf* bufs, size_t count, int flags, socket_addr_type* addr, std::size_t* addrlen, + void* control, std::size_t controllen, boost::system::error_code& ec); BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, size_t count, int flags, socket_addr_type* addr, - std::size_t* addrlen, boost::system::error_code& ec); + std::size_t* addrlen, void* control, std::size_t controllen, + boost::system::error_code& ec); #if defined(BOOST_ASIO_HAS_IOCP) @@ -162,6 +164,7 @@ BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s, buf* bufs, size_t count, int flags, socket_addr_type* addr, std::size_t* addrlen, + void* control, std::size_t controllen, boost::system::error_code& ec, size_t& bytes_transferred); #endif // defined(BOOST_ASIO_HAS_IOCP) --- boost/asio/detail/reactive_socket_recvfrom_op.hpp.orig 2010-10-25 20:00:45.117372071 -0400 +++ boost/asio/detail/reactive_socket_recvfrom_op.hpp 2010-10-25 20:04:16.904295102 -0400 @@ -57,6 +57,7 @@ bool result = socket_ops::non_blocking_recvfrom(o->socket_, bufs.buffers(), bufs.count(), o->flags_, o->sender_endpoint_.data(), &addr_len, + o->sender_endpoint_.control_msg(), o->sender_endpoint_.control_size(), o->ec_, o->bytes_transferred_); if (result && !o->ec_) --- boost/asio/ip/basic_endpoint.hpp.orig 2010-10-22 15:47:51.967270576 -0400 +++ boost/asio/ip/basic_endpoint.hpp 2010-10-22 15:48:42.529946860 -0400 @@ -136,6 +136,45 @@ impl_.resize(size); } + /// Get the underlying endpoint's first control header for recvfrom calls. + const struct cmsghdr* control_header_first() const + { + return impl_.control_header_first(); + } + + /// Get the underlying endpoint's next control header for recvfrom calls. + const struct cmsghdr* control_header_next(const cmsghdr* prev) const + { + return impl_.control_header_next(prev); + } + + /// Get the underlying size of the endpoint's buffer used to store + /// control messages. + template + T control_msg_data(const struct cmsghdr* cmsg) const + { + return impl_.control_msg_data(cmsg); + } + + /// Get the underlying endpoint's control message given its header. + void* control_msg() const + { + return impl_.control_msg(); + } + + /// Get the underlying size of the endpoint's buffer used to store + /// control messages. + std::size_t control_size() const + { + return impl_.control_size(); + } + + /// Set the size of the buffer used for storing control message. + void control_size(size_t size) + { + impl_.control_size(size); + } + /// Get the capacity of the endpoint in the native type. std::size_t capacity() const { --- boost/asio/ip/detail/endpoint.hpp.orig 2010-10-22 15:48:09.812150529 -0400 +++ boost/asio/ip/detail/endpoint.hpp 2010-10-22 15:51:03.106193184 -0400 @@ -77,6 +77,47 @@ return sizeof(boost::asio::detail::sockaddr_in6_type); } + /// Get the underlying endpoint's first control header for recvfrom calls. + const struct cmsghdr* control_header_first() const + { + return CMSG_FIRSTHDR(control_.msg()); + } + + /// Get the underlying endpoint's next control header for recvfrom calls. + const struct cmsghdr* control_header_next(const cmsghdr* prev) const + { + return static_cast( + CMSG_NXTHDR(const_cast(control_.msg()), + const_cast(prev))); + } + + /// Get the underlying size of the endpoint's buffer used to store + /// control messages. + template + T control_msg_data(const struct cmsghdr* cmsg) const + { + return reinterpret_cast(CMSG_DATA(cmsg)); + } + + /// Get the underlying endpoint's control message given its header. + void* control_msg() const + { + return control_.msg()->msg_control; + } + + /// Get the underlying size of the endpoint's buffer used to store + /// control messages. + std::size_t control_size() const + { + return control_.msg()->msg_controllen; + } + + /// Set the size of the buffer used for storing control message. + void control_size(size_t size) + { + control_.allocate(size); + } + // Set the underlying size of the endpoint in the native type. BOOST_ASIO_DECL void resize(std::size_t size); @@ -126,6 +167,36 @@ boost::asio::detail::sockaddr_in4_type v4; boost::asio::detail::sockaddr_in6_type v6; } data_; + + // Space for control message for receive + struct control + { + control() + { + memset(&msg_, 0, sizeof(msghdr)); + } + ~control() + { + allocate(0); + } + void allocate(size_t sz) + { + if (msg_.msg_control) + delete [] (char*)msg_.msg_control; + if (sz == 0) + return; + size_t n = sz > sizeof(struct cmsghdr) ? sz : sizeof(struct cmsghdr)+128; + msg_.msg_control = new char[n]; + msg_.msg_controllen = n; + memset(msg_.msg_control, 0, n); + } + + const msghdr* msg() const { return &msg_; } + const cmsghdr* cmsg() const { return static_cast(msg_.msg_control); } + size_t cmsg_len() { return msg_.msg_controllen; } + private: + msghdr msg_; + } control_; }; } // namespace detail