Browse Source

3. [func] each
bin/auth: removed custom query-processing code, changed
boost::asio code to use plain asio instead, and added asio
headers to the source tree. This allows building without
using an external boost library. (Trac #163, svn r1983)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1983 e5f2f494-b856-4b98-b285-d166d9295462

Evan Hunt 15 years ago
parent
commit
90c8141b69
100 changed files with 23561 additions and 59 deletions
  1. 5 0
      ChangeLog
  2. 0 3
      README
  3. 56 56
      configure.ac
  4. 101 0
      ext/asio/asio.hpp
  5. 803 0
      ext/asio/asio/basic_datagram_socket.hpp
  6. 445 0
      ext/asio/asio/basic_deadline_timer.hpp
  7. 97 0
      ext/asio/asio/basic_io_object.hpp
  8. 798 0
      ext/asio/asio/basic_raw_socket.hpp
  9. 622 0
      ext/asio/asio/basic_serial_port.hpp
  10. 1063 0
      ext/asio/asio/basic_socket.hpp
  11. 824 0
      ext/asio/asio/basic_socket_acceptor.hpp
  12. 156 0
      ext/asio/asio/basic_socket_iostream.hpp
  13. 295 0
      ext/asio/asio/basic_socket_streambuf.hpp
  14. 718 0
      ext/asio/asio/basic_stream_socket.hpp
  15. 348 0
      ext/asio/asio/basic_streambuf.hpp
  16. 1040 0
      ext/asio/asio/buffer.hpp
  17. 461 0
      ext/asio/asio/buffered_read_stream.hpp
  18. 29 0
      ext/asio/asio/buffered_read_stream_fwd.hpp
  19. 256 0
      ext/asio/asio/buffered_stream.hpp
  20. 29 0
      ext/asio/asio/buffered_stream_fwd.hpp
  21. 415 0
      ext/asio/asio/buffered_write_stream.hpp
  22. 29 0
      ext/asio/asio/buffered_write_stream_fwd.hpp
  23. 447 0
      ext/asio/asio/buffers_iterator.hpp
  24. 164 0
      ext/asio/asio/completion_condition.hpp
  25. 315 0
      ext/asio/asio/datagram_socket_service.hpp
  26. 37 0
      ext/asio/asio/deadline_timer.hpp
  27. 150 0
      ext/asio/asio/deadline_timer_service.hpp
  28. 65 0
      ext/asio/asio/detail/base_from_completion_cond.hpp
  29. 349 0
      ext/asio/asio/detail/bind_handler.hpp
  30. 70 0
      ext/asio/asio/detail/buffer_resize_guard.hpp
  31. 252 0
      ext/asio/asio/detail/buffer_sequence_adapter.hpp
  32. 127 0
      ext/asio/asio/detail/buffered_stream_storage.hpp
  33. 90 0
      ext/asio/asio/detail/call_stack.hpp
  34. 71 0
      ext/asio/asio/detail/completion_handler.hpp
  35. 280 0
      ext/asio/asio/detail/consuming_buffers.hpp
  36. 222 0
      ext/asio/asio/detail/deadline_timer_service.hpp
  37. 176 0
      ext/asio/asio/detail/descriptor_ops.hpp
  38. 453 0
      ext/asio/asio/detail/dev_poll_reactor.hpp
  39. 39 0
      ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
  40. 507 0
      ext/asio/asio/detail/epoll_reactor.hpp
  41. 46 0
      ext/asio/asio/detail/epoll_reactor_fwd.hpp
  42. 50 0
      ext/asio/asio/detail/event.hpp
  43. 166 0
      ext/asio/asio/detail/eventfd_select_interrupter.hpp
  44. 41 0
      ext/asio/asio/detail/fd_set_adapter.hpp
  45. 70 0
      ext/asio/asio/detail/fenced_block.hpp
  46. 63 0
      ext/asio/asio/detail/gcc_fenced_block.hpp
  47. 61 0
      ext/asio/asio/detail/gcc_x86_fenced_block.hpp
  48. 259 0
      ext/asio/asio/detail/handler_alloc_helpers.hpp
  49. 49 0
      ext/asio/asio/detail/handler_invoke_helpers.hpp
  50. 324 0
      ext/asio/asio/detail/hash_map.hpp
  51. 137 0
      ext/asio/asio/detail/io_control.hpp
  52. 485 0
      ext/asio/asio/detail/kqueue_reactor.hpp
  53. 44 0
      ext/asio/asio/detail/kqueue_reactor_fwd.hpp
  54. 59 0
      ext/asio/asio/detail/local_free_on_block_exit.hpp
  55. 57 0
      ext/asio/asio/detail/macos_fenced_block.hpp
  56. 50 0
      ext/asio/asio/detail/mutex.hpp
  57. 55 0
      ext/asio/asio/detail/noncopyable.hpp
  58. 77 0
      ext/asio/asio/detail/null_buffers_op.hpp
  59. 77 0
      ext/asio/asio/detail/null_event.hpp
  60. 43 0
      ext/asio/asio/detail/null_fenced_block.hpp
  61. 66 0
      ext/asio/asio/detail/null_mutex.hpp
  62. 63 0
      ext/asio/asio/detail/null_signal_blocker.hpp
  63. 68 0
      ext/asio/asio/detail/null_thread.hpp
  64. 70 0
      ext/asio/asio/detail/null_tss_ptr.hpp
  65. 340 0
      ext/asio/asio/detail/old_win_sdk_compat.hpp
  66. 156 0
      ext/asio/asio/detail/op_queue.hpp
  67. 43 0
      ext/asio/asio/detail/operation.hpp
  68. 120 0
      ext/asio/asio/detail/pipe_select_interrupter.hpp
  69. 88 0
      ext/asio/asio/detail/pop_options.hpp
  70. 114 0
      ext/asio/asio/detail/posix_event.hpp
  71. 81 0
      ext/asio/asio/detail/posix_fd_set_adapter.hpp
  72. 91 0
      ext/asio/asio/detail/posix_mutex.hpp
  73. 90 0
      ext/asio/asio/detail/posix_signal_blocker.hpp
  74. 129 0
      ext/asio/asio/detail/posix_thread.hpp
  75. 88 0
      ext/asio/asio/detail/posix_tss_ptr.hpp
  76. 114 0
      ext/asio/asio/detail/push_options.hpp
  77. 668 0
      ext/asio/asio/detail/reactive_descriptor_service.hpp
  78. 261 0
      ext/asio/asio/detail/reactive_serial_port_service.hpp
  79. 1744 0
      ext/asio/asio/detail/reactive_socket_service.hpp
  80. 34 0
      ext/asio/asio/detail/reactor.hpp
  81. 46 0
      ext/asio/asio/detail/reactor_fwd.hpp
  82. 60 0
      ext/asio/asio/detail/reactor_op.hpp
  83. 199 0
      ext/asio/asio/detail/reactor_op_queue.hpp
  84. 442 0
      ext/asio/asio/detail/resolver_service.hpp
  85. 91 0
      ext/asio/asio/detail/scoped_lock.hpp
  86. 47 0
      ext/asio/asio/detail/select_interrupter.hpp
  87. 374 0
      ext/asio/asio/detail/select_reactor.hpp
  88. 31 0
      ext/asio/asio/detail/select_reactor_fwd.hpp
  89. 49 0
      ext/asio/asio/detail/service_base.hpp
  90. 37 0
      ext/asio/asio/detail/service_id.hpp
  91. 275 0
      ext/asio/asio/detail/service_registry.hpp
  92. 30 0
      ext/asio/asio/detail/service_registry_fwd.hpp
  93. 50 0
      ext/asio/asio/detail/signal_blocker.hpp
  94. 51 0
      ext/asio/asio/detail/signal_init.hpp
  95. 95 0
      ext/asio/asio/detail/socket_holder.hpp
  96. 1912 0
      ext/asio/asio/detail/socket_ops.hpp
  97. 319 0
      ext/asio/asio/detail/socket_option.hpp
  98. 192 0
      ext/asio/asio/detail/socket_select_interrupter.hpp
  99. 216 0
      ext/asio/asio/detail/socket_types.hpp
  100. 0 0
      ext/asio/asio/detail/solaris_fenced_block.hpp

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+   3.	[func]		each
+	bin/auth: removed custom query-processing code, changed
+        boost::asio code to use plain asio instead, and added asio
+        headers to the source tree.  This allows building without
+        using an external boost library. (Trac #163, svn r1983)
    2.	[func]		jinmei
    2.	[func]		jinmei
 	lib/dns: added a separate signature for Name::split() as a
 	lib/dns: added a separate signature for Name::split() as a
 	convenient wrapper for common usage. (Trac #49, svn r1903)
 	convenient wrapper for common usage. (Trac #49, svn r1903)

+ 0 - 3
README

@@ -38,9 +38,6 @@ See the Guide for detailed installation directions.
 
 
 BUILDING
 BUILDING
 
 
-We recommend using the Boost libraries as it provides a safer TCP
-implementation in BIND 10.
-
 Simple build instructions:
 Simple build instructions:
 
 
   ./configure
   ./configure

+ 56 - 56
configure.ac

@@ -87,9 +87,21 @@ AC_SUBST(PYTHON_LIB)
 
 
 # TODO: check for _sqlite3.py module
 # TODO: check for _sqlite3.py module
 
 
-# default compiler warning settings
+#
+# B10_CXXFLAGS is the default C++ compiler flags.  This will (and should) be
+# used as the default value for each specifc AM_CXXFLAGS:
+# AM_CXXFLAGS = $(B10_CXXFLAGS)
+# AM_CXXFLAGS += ... # add module specific flags
+# We need this so that we can disable some specific compiler warnings per
+# module basis; since AM_CXXFLAGS are placed before CXXFLAGS, and since
+# gcc's -Wno-XXX option must be specified after -Wall or -Wextra, we cannot
+# specify the default warning flags in CXXFLAGS and let specific modules
+# "override" the default.
+#
+B10_CXXFLAGS=
+
 if test "X$GCC" = "Xyes"; then
 if test "X$GCC" = "Xyes"; then
-CXXFLAGS="$CXXFLAGS -g -Wall -Wextra -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare"
+B10_CXXFLAGS="-g -Wall -Wextra -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare"
 UNUSED_PARAM_ATTRIBUTE='__attribute__((unused))'
 UNUSED_PARAM_ATTRIBUTE='__attribute__((unused))'
 
 
 # Certain versions of gcc (g++) have a bug that incorrectly warns about
 # Certain versions of gcc (g++) have a bug that incorrectly warns about
@@ -97,23 +109,27 @@ UNUSED_PARAM_ATTRIBUTE='__attribute__((unused))'
 # translation unit.  For these versions we have to disable -Werror.
 # translation unit.  For these versions we have to disable -Werror.
 werror_ok=0
 werror_ok=0
 CXXFLAGS_SAVED="$CXXFLAGS"
 CXXFLAGS_SAVED="$CXXFLAGS"
-CXXFLAGS="$CXXFLAGS -Werror"
+CXXFLAGS="$CXXFLAGS $B10_CXXFLAGS -Werror"
 AC_MSG_CHECKING(for in-TU anonymous namespace breakage)
 AC_MSG_CHECKING(for in-TU anonymous namespace breakage)
 AC_TRY_COMPILE([namespace { class Foo {}; }
 AC_TRY_COMPILE([namespace { class Foo {}; }
 namespace isc {class Bar {Foo foo_;};} ],,
 namespace isc {class Bar {Foo foo_;};} ],,
 	[AC_MSG_RESULT(no)
 	[AC_MSG_RESULT(no)
-	 werror_ok=1],
+	 werror_ok=1
+	 B10_CXXFLAGS="$B10_CXXFLAGS -Werror"],
 	[AC_MSG_RESULT(yes)])
 	[AC_MSG_RESULT(yes)])
 CXXFLAGS="$CXXFLAGS_SAVED"
 CXXFLAGS="$CXXFLAGS_SAVED"
-fi
-AC_DEFINE_UNQUOTED(UNUSED_PARAM, $UNUSED_PARAM_ATTRIBUTE, Define to compiler keyword indicating a function argument is intentionally unused)
+fi				dnl GCC = yes
+
 AM_CONDITIONAL(GCC_WERROR_OK, test $werror_ok = 1)
 AM_CONDITIONAL(GCC_WERROR_OK, test $werror_ok = 1)
+AC_DEFINE_UNQUOTED(UNUSED_PARAM, $UNUSED_PARAM_ATTRIBUTE, Define to compiler keyword indicating a function argument is intentionally unused)
 
 
 # produce PIC unless we disable shared libraries. need this for python bindings.
 # produce PIC unless we disable shared libraries. need this for python bindings.
 if test $enable_shared != "no" -a "X$GCC" = "Xyes"; then
 if test $enable_shared != "no" -a "X$GCC" = "Xyes"; then
-   CXXFLAGS="$CXXFLAGS -fPIC"
+   B10_CXXFLAGS="$B10_CXXFLAGS -fPIC"
 fi
 fi
 
 
+AC_SUBST(B10_CXXFLAGS)
+
 # Checks for libraries.
 # Checks for libraries.
 
 
 AC_SEARCH_LIBS(inet_pton, [nsl])
 AC_SEARCH_LIBS(inet_pton, [nsl])
@@ -193,52 +209,6 @@ AC_HELP_STRING([--with-boost-lib=PATH],
    fi])
    fi])
 AC_SUBST(BOOST_LDFLAGS)
 AC_SUBST(BOOST_LDFLAGS)
 
 
-# Check availability of the Boost System library
-
-AC_MSG_CHECKING([for boost::system library])
-AC_ARG_WITH([boost-system],
-AC_HELP_STRING([--with-boost-system],
-  [specify whether to use the boost system library]),
-  [with_boost_system="$withval"], [with_boost_system="auto"])
-
-if test "$with_boost_system" != "no"; then
-	LDFLAGS_SAVED="$LDFLAGS"
-	LIBS_SAVED="$LIBS"
-	CPPFLAGS_SAVED="$CPPFLAGS"
-	CPPFLAGS="$CPPFLAGS -Iext"
-
-	for BOOST_TRY_LIB in boost_system boost_system-mt; do
-		LDFLAGS="$LDFLAGS_SAVED ${BOOST_LDFLAGS}"
-		LIBS="$LIBS_SAVED -l${BOOST_TRY_LIB}"
-		AC_TRY_LINK([#include <boost/system/error_code.hpp>],
-			[ boost::system::error_code error_code;
-			std::string message(error_code.message());
-			return 0; ],
-			[ AC_MSG_RESULT(yes)
-			BOOST_SYSTEM_LIB="-l${BOOST_TRY_LIB}"
-			],[])
-		if test "X${BOOST_SYSTEM_LIB}" != X; then
-        		break
-		fi
-	done
-
-	LDFLAGS="$LDFLAGS_SAVED"
-	CPPFLAGS="$CPPFLAGS_SAVED"
-	LIBS="$LIBS_SAVED"
-fi
-
-if test "X${BOOST_SYSTEM_LIB}" = X; then
-	AC_MSG_RESULT(no)
-	if test "$with_boost_system" = "yes"; then
-	   AC_MSG_ERROR([boost system library is requested but not found])
-	fi
-else
-	AC_DEFINE(HAVE_BOOST_SYSTEM, 1, Define to 1 if boost system library is available)
-fi
-
-AM_CONDITIONAL(HAVE_BOOST_SYSTEM, test "X${BOOST_SYSTEM_LIB}" != X)
-AC_SUBST(BOOST_SYSTEM_LIB)
-
 # Check availability of the Boost Python library
 # Check availability of the Boost Python library
 
 
 AC_MSG_CHECKING([for boost::python library])
 AC_MSG_CHECKING([for boost::python library])
@@ -340,19 +310,49 @@ AC_SUBST(GTEST_LDADD)
 
 
 PKG_CHECK_MODULES(SQLITE, sqlite3 >= 3.3.9, enable_features="$enable_features SQLite3")
 PKG_CHECK_MODULES(SQLITE, sqlite3 >= 3.3.9, enable_features="$enable_features SQLite3")
 
 
+#
+# ASIO: we extensively use it as the C++ event management module.
+#
+# Use local ASIO headers from ext
+#
+CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/ext/asio"
+#
+# kqueue portability: ASIO uses kqueue by default if it's available (it's
+# generally available in BSD variants).  Unfortunately, some public
+# implementation of kqueue forces a conversion from a pointer to an integer,
+# which is prohibited in C++ unless reinterpret_cast, C++'s most evil beast
+# (and ASIO doesn't use it anyway) is used.  This will cause build error for
+# some of our C++ files including ASIO header files.  The following check
+# detects such cases and tells ASIO not to use kqueue if so.
+AC_CHECK_FUNC(kqueue, ac_cv_have_kqueue=yes, ac_cv_have_kqueue=no)
+case $ac_cv_have_kqueue in
+yes)
+	AC_MSG_CHECKING([whether kqueue EV_SET compiles in C++])
+	AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/event.h>],
+[char* udata;
+EV_SET(NULL, 0, 0, 0, 0, 0, udata);],
+	[AC_MSG_RESULT(yes)],
+	[AC_MSG_RESULT([no, disable kqueue for ASIO])
+	 CPPFLAGS="$CPPFLAGS -DASIO_DISABLE_KQUEUE=1"
+	])
+esac
+
 # Check for headers from required devel kits.
 # Check for headers from required devel kits.
 # boost/shared_ptr.hpp is in ext in svn but not in tarball.
 # boost/shared_ptr.hpp is in ext in svn but not in tarball.
 CPPFLAGS_SAVED=$CPPFLAGS
 CPPFLAGS_SAVED=$CPPFLAGS
 if test "X$BOOST_INCLUDES" = "X"; then
 if test "X$BOOST_INCLUDES" = "X"; then
 	# abs_top_srcdir not defined yet
 	# abs_top_srcdir not defined yet
 	# so this is only useful to check.  We'll replace it after the check.
 	# so this is only useful to check.  We'll replace it after the check.
-	CPPFLAGS="$CPPFLAGS -Iext"
+	CPPFLAGS="$CPPFLAGS -Iext/boost"
 fi
 fi
 AC_CHECK_HEADERS([boost/shared_ptr.hpp boost/foreach.hpp],,
 AC_CHECK_HEADERS([boost/shared_ptr.hpp boost/foreach.hpp],,
   AC_MSG_ERROR([Missing required header files.]))
   AC_MSG_ERROR([Missing required header files.]))
 CPPFLAGS=$CPPFLAGS_SAVED
 CPPFLAGS=$CPPFLAGS_SAVED
 if test "X$BOOST_INCLUDES" = "X"; then
 if test "X$BOOST_INCLUDES" = "X"; then
-	CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/ext"
+	CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/ext/boost"
 fi
 fi
 
 
 AC_ARG_ENABLE(man, [AC_HELP_STRING([--enable-man],
 AC_ARG_ENABLE(man, [AC_HELP_STRING([--enable-man],
@@ -473,9 +473,9 @@ Flags:
   CPPFLAGS:      $CPPFLAGS
   CPPFLAGS:      $CPPFLAGS
   CFLAGS:        $CFLAGS
   CFLAGS:        $CFLAGS
   CXXFLAGS:      $CXXFLAGS
   CXXFLAGS:      $CXXFLAGS
+  B10_CXXFLAGS:  $B10_CXXFLAGS
 dnl includes too
 dnl includes too
   Boost Python:  $BOOST_PYTHON_LIB
   Boost Python:  $BOOST_PYTHON_LIB
-  Boost System:  $BOOST_SYSTEM_LIB
   SQLite:	 $SQLITE_CFLAGS
   SQLite:	 $SQLITE_CFLAGS
                  $SQLITE_LIBS
                  $SQLITE_LIBS
 
 

+ 101 - 0
ext/asio/asio.hpp

@@ -0,0 +1,101 @@
+//
+// asio.hpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_HPP
+#define ASIO_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/basic_datagram_socket.hpp"
+#include "asio/basic_deadline_timer.hpp"
+#include "asio/basic_io_object.hpp"
+#include "asio/basic_raw_socket.hpp"
+#include "asio/basic_serial_port.hpp"
+#include "asio/basic_socket_acceptor.hpp"
+#include "asio/basic_socket_iostream.hpp"
+#include "asio/basic_socket_streambuf.hpp"
+#include "asio/basic_stream_socket.hpp"
+#include "asio/basic_streambuf.hpp"
+#include "asio/buffer.hpp"
+#include "asio/buffered_read_stream_fwd.hpp"
+#include "asio/buffered_read_stream.hpp"
+#include "asio/buffered_stream_fwd.hpp"
+#include "asio/buffered_stream.hpp"
+#include "asio/buffered_write_stream_fwd.hpp"
+#include "asio/buffered_write_stream.hpp"
+#include "asio/buffers_iterator.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/datagram_socket_service.hpp"
+#include "asio/deadline_timer_service.hpp"
+#include "asio/deadline_timer.hpp"
+#include "asio/error.hpp"
+#include "asio/error_code.hpp"
+#include "asio/handler_alloc_hook.hpp"
+#include "asio/handler_invoke_hook.hpp"
+#include "asio/io_service.hpp"
+#include "asio/ip/address.hpp"
+#include "asio/ip/address_v4.hpp"
+#include "asio/ip/address_v6.hpp"
+#include "asio/ip/basic_endpoint.hpp"
+#include "asio/ip/basic_resolver.hpp"
+#include "asio/ip/basic_resolver_entry.hpp"
+#include "asio/ip/basic_resolver_iterator.hpp"
+#include "asio/ip/basic_resolver_query.hpp"
+#include "asio/ip/host_name.hpp"
+#include "asio/ip/icmp.hpp"
+#include "asio/ip/multicast.hpp"
+#include "asio/ip/resolver_query_base.hpp"
+#include "asio/ip/resolver_service.hpp"
+#include "asio/ip/tcp.hpp"
+#include "asio/ip/udp.hpp"
+#include "asio/ip/unicast.hpp"
+#include "asio/ip/v6_only.hpp"
+#include "asio/is_read_buffered.hpp"
+#include "asio/is_write_buffered.hpp"
+#include "asio/local/basic_endpoint.hpp"
+#include "asio/local/connect_pair.hpp"
+#include "asio/local/datagram_protocol.hpp"
+#include "asio/local/stream_protocol.hpp"
+#include "asio/placeholders.hpp"
+#include "asio/posix/basic_descriptor.hpp"
+#include "asio/posix/basic_stream_descriptor.hpp"
+#include "asio/posix/descriptor_base.hpp"
+#include "asio/posix/stream_descriptor.hpp"
+#include "asio/posix/stream_descriptor_service.hpp"
+#include "asio/raw_socket_service.hpp"
+#include "asio/read.hpp"
+#include "asio/read_at.hpp"
+#include "asio/read_until.hpp"
+#include "asio/serial_port.hpp"
+#include "asio/serial_port_base.hpp"
+#include "asio/serial_port_service.hpp"
+#include "asio/socket_acceptor_service.hpp"
+#include "asio/socket_base.hpp"
+#include "asio/strand.hpp"
+#include "asio/stream_socket_service.hpp"
+#include "asio/streambuf.hpp"
+#include "asio/system_error.hpp"
+#include "asio/thread.hpp"
+#include "asio/time_traits.hpp"
+#include "asio/version.hpp"
+#include "asio/windows/basic_handle.hpp"
+#include "asio/windows/basic_random_access_handle.hpp"
+#include "asio/windows/basic_stream_handle.hpp"
+#include "asio/windows/overlapped_ptr.hpp"
+#include "asio/windows/random_access_handle.hpp"
+#include "asio/windows/random_access_handle_service.hpp"
+#include "asio/windows/stream_handle.hpp"
+#include "asio/windows/stream_handle_service.hpp"
+#include "asio/write.hpp"
+#include "asio/write_at.hpp"
+
+#endif // ASIO_HPP

+ 803 - 0
ext/asio/asio/basic_datagram_socket.hpp

@@ -0,0 +1,803 @@
+//
+// basic_datagram_socket.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DATAGRAM_SOCKET_HPP
+#define ASIO_BASIC_DATAGRAM_SOCKET_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_socket.hpp"
+#include "asio/datagram_socket_service.hpp"
+#include "asio/error.hpp"
+#include "asio/detail/throw_error.hpp"
+
+namespace asio {
+
+/// Provides datagram-oriented socket functionality.
+/**
+ * The basic_datagram_socket class template provides asynchronous and blocking
+ * datagram-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol,
+    typename DatagramSocketService = datagram_socket_service<Protocol> >
+class basic_datagram_socket
+  : public basic_socket<Protocol, DatagramSocketService>
+{
+public:
+  /// The native representation of a socket.
+  typedef typename DatagramSocketService::native_type native_type;
+
+  /// The protocol type.
+  typedef Protocol protocol_type;
+
+  /// The endpoint type.
+  typedef typename Protocol::endpoint endpoint_type;
+
+  /// Construct a basic_datagram_socket without opening it.
+  /**
+   * This constructor creates a datagram socket without opening it. The open()
+   * function must be called before data can be sent or received on the socket.
+   *
+   * @param io_service The io_service object that the datagram socket will use
+   * to dispatch handlers for any asynchronous operations performed on the
+   * socket.
+   */
+  explicit basic_datagram_socket(asio::io_service& io_service)
+    : basic_socket<Protocol, DatagramSocketService>(io_service)
+  {
+  }
+
+  /// Construct and open a basic_datagram_socket.
+  /**
+   * This constructor creates and opens a datagram socket.
+   *
+   * @param io_service The io_service object that the datagram 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_datagram_socket(asio::io_service& io_service,
+      const protocol_type& protocol)
+    : basic_socket<Protocol, DatagramSocketService>(io_service, protocol)
+  {
+  }
+
+  /// Construct a basic_datagram_socket, opening it and binding it to the given
+  /// local endpoint.
+  /**
+   * This constructor creates a datagram 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 datagram 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 datagram
+   * socket will be bound.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  basic_datagram_socket(asio::io_service& io_service,
+      const endpoint_type& endpoint)
+    : basic_socket<Protocol, DatagramSocketService>(io_service, endpoint)
+  {
+  }
+
+  /// Construct a basic_datagram_socket on an existing native socket.
+  /**
+   * This constructor creates a datagram socket object to hold an existing
+   * native socket.
+   *
+   * @param io_service The io_service object that the datagram 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_datagram_socket(asio::io_service& io_service,
+      const protocol_type& protocol, const native_type& native_socket)
+    : basic_socket<Protocol, DatagramSocketService>(
+        io_service, protocol, native_socket)
+  {
+  }
+
+  /// Send some data on a connected socket.
+  /**
+   * This function is used to send data on the datagram socket. The function
+   * call will block until the data has been sent successfully or an error
+   * occurs.
+   *
+   * @param buffers One ore more data buffers to be sent on the socket.
+   *
+   * @returns The number of bytes sent.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note The send operation can only be used with a connected socket. Use
+   * the send_to function to send data on an unconnected datagram socket.
+   *
+   * @par Example
+   * To send a single data buffer use the @ref buffer function as follows:
+   * @code socket.send(asio::buffer(data, size)); @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)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Send some data on a connected socket.
+  /**
+   * This function is used to send data on the datagram socket. The function
+   * call will block until the data has been sent successfully or an error
+   * occurs.
+   *
+   * @param buffers One ore 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.
+   *
+   * @note The send operation can only be used with a connected socket. Use
+   * the send_to function to send data on an unconnected datagram socket.
+   */
+  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 a connected socket.
+  /**
+   * This function is used to send data on the datagram socket. The function
+   * call will block until the data has been sent successfully or an 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.
+   *
+   * @note The send operation can only be used with a connected socket. Use
+   * the send_to function to send data on an unconnected datagram socket.
+   */
+  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 on a connected socket.
+  /**
+   * This function is used to send data on the datagram socket. The function
+   * call will block until the data has been sent successfully or an error
+   * occurs.
+   *
+   * @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 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().
+   *
+   * @note The async_send operation can only be used with a connected socket.
+   * Use the async_send_to function to send data on an unconnected datagram
+   * socket.
+   *
+   * @par Example
+   * To send a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.async_send(asio::buffer(data, size), 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, WriteHandler handler)
+  {
+    this->service.async_send(this->implementation, buffers, 0, handler);
+  }
+
+  /// Start an asynchronous send on a connected socket.
+  /**
+   * This function is used to send data on the datagram socket. The function
+   * call will block until the data has been sent successfully or an error
+   * occurs.
+   *
+   * @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().
+   *
+   * @note The async_send operation can only be used with a connected socket.
+   * Use the async_send_to function to send data on an unconnected datagram
+   * socket.
+   */
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_send(const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, WriteHandler handler)
+  {
+    this->service.async_send(this->implementation, buffers, flags, handler);
+  }
+
+  /// Send a datagram to the specified endpoint.
+  /**
+   * This function is used to send a datagram to the specified remote endpoint.
+   * The function call will block until the data has been sent successfully or
+   * an error occurs.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   *
+   * @param destination The remote endpoint to which the data will be sent.
+   *
+   * @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
+   * asio::ip::udp::endpoint destination(
+   *     asio::ip::address::from_string("1.2.3.4"), 12345);
+   * socket.send_to(asio::buffer(data, size), destination);
+   * @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_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send_to(
+        this->implementation, buffers, destination, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Send a datagram to the specified endpoint.
+  /**
+   * This function is used to send a datagram to the specified remote endpoint.
+   * The function call will block until the data has been sent successfully or
+   * an error occurs.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   *
+   * @param destination The remote endpoint to which the data will be sent.
+   *
+   * @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.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t send_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, socket_base::message_flags flags)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send_to(
+        this->implementation, buffers, destination, flags, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Send a datagram to the specified endpoint.
+  /**
+   * This function is used to send a datagram to the specified remote endpoint.
+   * The function call will block until the data has been sent successfully or
+   * an error occurs.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   *
+   * @param destination The remote endpoint to which the data will be sent.
+   *
+   * @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.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t send_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, socket_base::message_flags flags,
+      asio::error_code& ec)
+  {
+    return this->service.send_to(this->implementation,
+        buffers, destination, flags, ec);
+  }
+
+  /// Start an asynchronous send.
+  /**
+   * This function is used to asynchronously send a datagram to the specified
+   * remote endpoint. The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   * 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 destination The remote endpoint to which the data will be sent.
+   * Copies will be made of the endpoint as required.
+   *
+   * @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
+   * asio::ip::udp::endpoint destination(
+   *     asio::ip::address::from_string("1.2.3.4"), 12345);
+   * socket.async_send_to(
+   *     asio::buffer(data, size), destination, 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_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, WriteHandler handler)
+  {
+    this->service.async_send_to(this->implementation, buffers, destination, 0,
+        handler);
+  }
+
+  /// Start an asynchronous send.
+  /**
+   * This function is used to asynchronously send a datagram to the specified
+   * remote endpoint. The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   * 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 destination The remote endpoint to which the data will be sent.
+   * Copies will be made of the endpoint as required.
+   *
+   * @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().
+   */
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_send_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, socket_base::message_flags flags,
+      WriteHandler handler)
+  {
+    this->service.async_send_to(this->implementation, buffers, destination,
+        flags, handler);
+  }
+
+  /// Receive some data on a connected socket.
+  /**
+   * This function is used to receive data on the datagram socket. The function
+   * call will block until data has been received successfully or an error
+   * occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note The receive operation can only be used with a connected socket. Use
+   * the receive_from function to receive data on an unconnected datagram
+   * socket.
+   *
+   * @par Example
+   * To receive into a single data buffer use the @ref buffer function as
+   * follows:
+   * @code socket.receive(asio::buffer(data, size)); @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)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive(
+        this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Receive some data on a connected socket.
+  /**
+   * This function is used to receive data on the datagram socket. The function
+   * call will block until data has been received successfully or an error
+   * occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note The receive operation can only be used with a connected socket. Use
+   * the receive_from function to receive data on an unconnected datagram
+   * socket.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive(const MutableBufferSequence& buffers,
+      socket_base::message_flags flags)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive(
+        this->implementation, buffers, 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 datagram socket. The function
+   * call will block until data has been received successfully or an error
+   * occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes received.
+   *
+   * @note The receive operation can only be used with a connected socket. Use
+   * the receive_from function to receive data on an unconnected datagram
+   * socket.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive(const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    return this->service.receive(this->implementation, buffers, flags, ec);
+  }
+
+  /// Start an asynchronous receive on a connected socket.
+  /**
+   * This function is used to asynchronously receive data from the datagram
+   * 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 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().
+   *
+   * @note The async_receive operation can only be used with a connected socket.
+   * Use the async_receive_from function to receive data on an unconnected
+   * datagram socket.
+   *
+   * @par Example
+   * To receive into a single data buffer use the @ref buffer function as
+   * follows:
+   * @code
+   * socket.async_receive(asio::buffer(data, size), 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, ReadHandler handler)
+  {
+    this->service.async_receive(this->implementation, buffers, 0, handler);
+  }
+
+  /// Start an asynchronous receive on a connected socket.
+  /**
+   * This function is used to asynchronously receive data from the datagram
+   * 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 flags Flags specifying how the receive call is to be made.
+   *
+   * @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().
+   *
+   * @note The async_receive operation can only be used with a connected socket.
+   * Use the async_receive_from function to receive data on an unconnected
+   * datagram socket.
+   */
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_receive(const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, ReadHandler handler)
+  {
+    this->service.async_receive(this->implementation, buffers, flags, handler);
+  }
+
+  /// Receive a datagram with the endpoint of the sender.
+  /**
+   * This function is used to receive a datagram. The function call will block
+   * until data has been received successfully or an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the datagram.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * To receive into a single data buffer use the @ref buffer function as
+   * follows:
+   * @code
+   * asio::ip::udp::endpoint sender_endpoint;
+   * socket.receive_from(
+   *     asio::buffer(data, size), sender_endpoint);
+   * @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_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive_from(
+        this->implementation, buffers, sender_endpoint, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+  
+  /// Receive a datagram with the endpoint of the sender.
+  /**
+   * This function is used to receive a datagram. The function call will block
+   * until data has been received successfully or an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the datagram.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, socket_base::message_flags flags)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive_from(
+        this->implementation, buffers, sender_endpoint, flags, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+  
+  /// Receive a datagram with the endpoint of the sender.
+  /**
+   * This function is used to receive a datagram. The function call will block
+   * until data has been received successfully or an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the datagram.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes received.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, socket_base::message_flags flags,
+      asio::error_code& ec)
+  {
+    return this->service.receive_from(this->implementation, buffers,
+        sender_endpoint, flags, ec);
+  }
+
+  /// Start an asynchronous receive.
+  /**
+   * This function is used to asynchronously receive a datagram. 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 sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the datagram. Ownership of the sender_endpoint object
+   * is retained by the caller, which must guarantee that it is 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_from(
+   *     asio::buffer(data, size), 0, sender_endpoint, 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_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, ReadHandler handler)
+  {
+    this->service.async_receive_from(this->implementation, buffers,
+        sender_endpoint, 0, handler);
+  }
+
+  /// Start an asynchronous receive.
+  /**
+   * This function is used to asynchronously receive a datagram. 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 sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the datagram. Ownership of the sender_endpoint object
+   * is retained by the caller, which must guarantee that it is valid until the
+   * handler is called.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @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().
+   */
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_receive_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, socket_base::message_flags flags,
+      ReadHandler handler)
+  {
+    this->service.async_receive_from(this->implementation, buffers,
+        sender_endpoint, flags, handler);
+  }
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP

+ 445 - 0
ext/asio/asio/basic_deadline_timer.hpp

@@ -0,0 +1,445 @@
+//
+// basic_deadline_timer.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DEADLINE_TIMER_HPP
+#define ASIO_BASIC_DEADLINE_TIMER_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_io_object.hpp"
+#include "asio/deadline_timer_service.hpp"
+#include "asio/error.hpp"
+#include "asio/detail/throw_error.hpp"
+
+namespace asio {
+
+/// Provides waitable timer functionality.
+/**
+ * The basic_deadline_timer class template provides the ability to perform a
+ * blocking or asynchronous wait for a timer to expire.
+ *
+ * A deadline timer is always in one of two states: "expired" or "not expired".
+ * If the wait() or async_wait() function is called on an expired timer, the
+ * wait operation will complete immediately.
+ *
+ * Most applications will use the asio::deadline_timer typedef.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Examples
+ * Performing a blocking wait:
+ * @code
+ * // Construct a timer without setting an expiry time.
+ * asio::deadline_timer timer(io_service);
+ *
+ * // Set an expiry time relative to now.
+ * timer.expires_from_now(boost::posix_time::seconds(5));
+ *
+ * // Wait for the timer to expire.
+ * timer.wait();
+ * @endcode
+ *
+ * @par 
+ * Performing an asynchronous wait:
+ * @code
+ * void handler(const asio::error_code& error)
+ * {
+ *   if (!error)
+ *   {
+ *     // Timer expired.
+ *   }
+ * }
+ *
+ * ...
+ *
+ * // Construct a timer with an absolute expiry time.
+ * asio::deadline_timer timer(io_service,
+ *     boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
+ *
+ * // Start an asynchronous wait.
+ * timer.async_wait(handler);
+ * @endcode
+ *
+ * @par Changing an active deadline_timer's expiry time
+ *
+ * Changing the expiry time of a timer while there are pending asynchronous
+ * waits causes those wait operations to be cancelled. To ensure that the action
+ * associated with the timer is performed only once, use something like this:
+ * used:
+ *
+ * @code
+ * void on_some_event()
+ * {
+ *   if (my_timer.expires_from_now(seconds(5)) > 0)
+ *   {
+ *     // We managed to cancel the timer. Start new asynchronous wait.
+ *     my_timer.async_wait(on_timeout);
+ *   }
+ *   else
+ *   {
+ *     // Too late, timer has already expired!
+ *   }
+ * }
+ *
+ * void on_timeout(const asio::error_code& e)
+ * {
+ *   if (e != asio::error::operation_aborted)
+ *   {
+ *     // Timer was not cancelled, take necessary action.
+ *   }
+ * }
+ * @endcode
+ *
+ * @li The asio::basic_deadline_timer::expires_from_now() function
+ * cancels any pending asynchronous waits, and returns the number of
+ * asynchronous waits that were cancelled. If it returns 0 then you were too
+ * late and the wait handler has already been executed, or will soon be
+ * executed. If it returns 1 then the wait handler was successfully cancelled.
+ *
+ * @li If a wait handler is cancelled, the asio::error_code passed to
+ * it contains the value asio::error::operation_aborted.
+ */
+template <typename Time,
+    typename TimeTraits = asio::time_traits<Time>,
+    typename TimerService = deadline_timer_service<Time, TimeTraits> >
+class basic_deadline_timer
+  : public basic_io_object<TimerService>
+{
+public:
+  /// The time traits type.
+  typedef TimeTraits traits_type;
+
+  /// The time type.
+  typedef typename traits_type::time_type time_type;
+
+  /// The duration type.
+  typedef typename traits_type::duration_type duration_type;
+
+  /// Constructor.
+  /**
+   * This constructor creates a timer without setting an expiry time. The
+   * expires_at() or expires_from_now() functions must be called to set an
+   * expiry time before the timer can be waited on.
+   *
+   * @param io_service The io_service object that the timer will use to dispatch
+   * handlers for any asynchronous operations performed on the timer.
+   */
+  explicit basic_deadline_timer(asio::io_service& io_service)
+    : basic_io_object<TimerService>(io_service)
+  {
+  }
+
+  /// Constructor to set a particular expiry time as an absolute time.
+  /**
+   * This constructor creates a timer and sets the expiry time.
+   *
+   * @param io_service The io_service object that the timer will use to dispatch
+   * handlers for any asynchronous operations performed on the timer.
+   *
+   * @param expiry_time The expiry time to be used for the timer, expressed
+   * as an absolute time.
+   */
+  basic_deadline_timer(asio::io_service& io_service,
+      const time_type& expiry_time)
+    : basic_io_object<TimerService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.expires_at(this->implementation, expiry_time, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Constructor to set a particular expiry time relative to now.
+  /**
+   * This constructor creates a timer and sets the expiry time.
+   *
+   * @param io_service The io_service object that the timer will use to dispatch
+   * handlers for any asynchronous operations performed on the timer.
+   *
+   * @param expiry_time The expiry time to be used for the timer, relative to
+   * now.
+   */
+  basic_deadline_timer(asio::io_service& io_service,
+      const duration_type& expiry_time)
+    : basic_io_object<TimerService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.expires_from_now(this->implementation, expiry_time, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Cancel any asynchronous operations that are waiting on the timer.
+  /**
+   * This function forces the completion of any pending asynchronous wait
+   * operations against the timer. The handler for each cancelled operation will
+   * be invoked with the asio::error::operation_aborted error code.
+   *
+   * Cancelling the timer does not change the expiry time.
+   *
+   * @return The number of asynchronous operations that were cancelled.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note If the timer has already expired when cancel() is called, then the
+   * handlers for asynchronous wait operations will:
+   *
+   * @li have already been invoked; or
+   *
+   * @li have been queued for invocation in the near future.
+   *
+   * These handlers can no longer be cancelled, and therefore are passed an
+   * error code that indicates the successful completion of the wait operation.
+   */
+  std::size_t cancel()
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.cancel(this->implementation, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Cancel any asynchronous operations that are waiting on the timer.
+  /**
+   * This function forces the completion of any pending asynchronous wait
+   * operations against the timer. The handler for each cancelled operation will
+   * be invoked with the asio::error::operation_aborted error code.
+   *
+   * Cancelling the timer does not change the expiry time.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @return The number of asynchronous operations that were cancelled.
+   *
+   * @note If the timer has already expired when cancel() is called, then the
+   * handlers for asynchronous wait operations will:
+   *
+   * @li have already been invoked; or
+   *
+   * @li have been queued for invocation in the near future.
+   *
+   * These handlers can no longer be cancelled, and therefore are passed an
+   * error code that indicates the successful completion of the wait operation.
+   */
+  std::size_t cancel(asio::error_code& ec)
+  {
+    return this->service.cancel(this->implementation, ec);
+  }
+
+  /// Get the timer's expiry time as an absolute time.
+  /**
+   * This function may be used to obtain the timer's current expiry time.
+   * Whether the timer has expired or not does not affect this value.
+   */
+  time_type expires_at() const
+  {
+    return this->service.expires_at(this->implementation);
+  }
+
+  /// Set the timer's expiry time as an absolute time.
+  /**
+   * This function sets the expiry time. Any pending asynchronous wait
+   * operations will be cancelled. The handler for each cancelled operation will
+   * be invoked with the asio::error::operation_aborted error code.
+   *
+   * @param expiry_time The expiry time to be used for the timer.
+   *
+   * @return The number of asynchronous operations that were cancelled.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note If the timer has already expired when expires_at() is called, then
+   * the handlers for asynchronous wait operations will:
+   *
+   * @li have already been invoked; or
+   *
+   * @li have been queued for invocation in the near future.
+   *
+   * These handlers can no longer be cancelled, and therefore are passed an
+   * error code that indicates the successful completion of the wait operation.
+   */
+  std::size_t expires_at(const time_type& expiry_time)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.expires_at(
+        this->implementation, expiry_time, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Set the timer's expiry time as an absolute time.
+  /**
+   * This function sets the expiry time. Any pending asynchronous wait
+   * operations will be cancelled. The handler for each cancelled operation will
+   * be invoked with the asio::error::operation_aborted error code.
+   *
+   * @param expiry_time The expiry time to be used for the timer.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @return The number of asynchronous operations that were cancelled.
+   *
+   * @note If the timer has already expired when expires_at() is called, then
+   * the handlers for asynchronous wait operations will:
+   *
+   * @li have already been invoked; or
+   *
+   * @li have been queued for invocation in the near future.
+   *
+   * These handlers can no longer be cancelled, and therefore are passed an
+   * error code that indicates the successful completion of the wait operation.
+   */
+  std::size_t expires_at(const time_type& expiry_time,
+      asio::error_code& ec)
+  {
+    return this->service.expires_at(this->implementation, expiry_time, ec);
+  }
+
+  /// Get the timer's expiry time relative to now.
+  /**
+   * This function may be used to obtain the timer's current expiry time.
+   * Whether the timer has expired or not does not affect this value.
+   */
+  duration_type expires_from_now() const
+  {
+    return this->service.expires_from_now(this->implementation);
+  }
+
+  /// Set the timer's expiry time relative to now.
+  /**
+   * This function sets the expiry time. Any pending asynchronous wait
+   * operations will be cancelled. The handler for each cancelled operation will
+   * be invoked with the asio::error::operation_aborted error code.
+   *
+   * @param expiry_time The expiry time to be used for the timer.
+   *
+   * @return The number of asynchronous operations that were cancelled.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note If the timer has already expired when expires_from_now() is called,
+   * then the handlers for asynchronous wait operations will:
+   *
+   * @li have already been invoked; or
+   *
+   * @li have been queued for invocation in the near future.
+   *
+   * These handlers can no longer be cancelled, and therefore are passed an
+   * error code that indicates the successful completion of the wait operation.
+   */
+  std::size_t expires_from_now(const duration_type& expiry_time)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.expires_from_now(
+        this->implementation, expiry_time, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Set the timer's expiry time relative to now.
+  /**
+   * This function sets the expiry time. Any pending asynchronous wait
+   * operations will be cancelled. The handler for each cancelled operation will
+   * be invoked with the asio::error::operation_aborted error code.
+   *
+   * @param expiry_time The expiry time to be used for the timer.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @return The number of asynchronous operations that were cancelled.
+   *
+   * @note If the timer has already expired when expires_from_now() is called,
+   * then the handlers for asynchronous wait operations will:
+   *
+   * @li have already been invoked; or
+   *
+   * @li have been queued for invocation in the near future.
+   *
+   * These handlers can no longer be cancelled, and therefore are passed an
+   * error code that indicates the successful completion of the wait operation.
+   */
+  std::size_t expires_from_now(const duration_type& expiry_time,
+      asio::error_code& ec)
+  {
+    return this->service.expires_from_now(
+        this->implementation, expiry_time, ec);
+  }
+
+  /// Perform a blocking wait on the timer.
+  /**
+   * This function is used to wait for the timer to expire. This function
+   * blocks and does not return until the timer has expired.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void wait()
+  {
+    asio::error_code ec;
+    this->service.wait(this->implementation, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Perform a blocking wait on the timer.
+  /**
+   * This function is used to wait for the timer to expire. This function
+   * blocks and does not return until the timer has expired.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  void wait(asio::error_code& ec)
+  {
+    this->service.wait(this->implementation, ec);
+  }
+
+  /// Start an asynchronous wait on the timer.
+  /**
+   * This function may be used to initiate an asynchronous wait against the
+   * timer. It always returns immediately.
+   *
+   * For each call to async_wait(), the supplied handler will be called exactly
+   * once. The handler will be called when:
+   *
+   * @li The timer has expired.
+   *
+   * @li The timer was cancelled, in which case the handler is passed the error
+   * code asio::error::operation_aborted.
+   *
+   * @param handler The handler to be called when the timer expires. 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.
+   * ); @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().
+   */
+  template <typename WaitHandler>
+  void async_wait(WaitHandler handler)
+  {
+    this->service.async_wait(this->implementation, handler);
+  }
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_DEADLINE_TIMER_HPP

+ 97 - 0
ext/asio/asio/basic_io_object.hpp

@@ -0,0 +1,97 @@
+//
+// basic_io_object.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_IO_OBJECT_HPP
+#define ASIO_BASIC_IO_OBJECT_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/io_service.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+
+/// Base class for all I/O objects.
+template <typename IoObjectService>
+class basic_io_object
+  : private noncopyable
+{
+public:
+  /// The type of the service that will be used to provide I/O operations.
+  typedef IoObjectService service_type;
+
+  /// The underlying implementation type of I/O object.
+  typedef typename service_type::implementation_type implementation_type;
+
+  /// (Deprecated: use get_io_service().) Get the io_service associated with
+  /// the object.
+  /**
+   * This function may be used to obtain the io_service object that the I/O
+   * object uses to dispatch handlers for asynchronous operations.
+   *
+   * @return A reference to the io_service object that the I/O object will use
+   * to dispatch handlers. Ownership is not transferred to the caller.
+   */
+  asio::io_service& io_service()
+  {
+    return service.get_io_service();
+  }
+
+  /// Get the io_service associated with the object.
+  /**
+   * This function may be used to obtain the io_service object that the I/O
+   * object uses to dispatch handlers for asynchronous operations.
+   *
+   * @return A reference to the io_service object that the I/O object will use
+   * to dispatch handlers. Ownership is not transferred to the caller.
+   */
+  asio::io_service& get_io_service()
+  {
+    return service.get_io_service();
+  }
+
+protected:
+  /// Construct a basic_io_object.
+  /**
+   * Performs:
+   * @code service.construct(implementation); @endcode
+   */
+  explicit basic_io_object(asio::io_service& io_service)
+    : service(asio::use_service<IoObjectService>(io_service))
+  {
+    service.construct(implementation);
+  }
+
+  /// Protected destructor to prevent deletion through this type.
+  /**
+   * Performs:
+   * @code service.destroy(implementation); @endcode
+   */
+  ~basic_io_object()
+  {
+    service.destroy(implementation);
+  }
+
+  /// The service associated with the I/O object.
+  service_type& service;
+
+  /// The underlying implementation of the I/O object.
+  implementation_type implementation;
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_IO_OBJECT_HPP

+ 798 - 0
ext/asio/asio/basic_raw_socket.hpp

@@ -0,0 +1,798 @@
+//
+// basic_raw_socket.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_RAW_SOCKET_HPP
+#define ASIO_BASIC_RAW_SOCKET_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_socket.hpp"
+#include "asio/raw_socket_service.hpp"
+#include "asio/error.hpp"
+#include "asio/detail/throw_error.hpp"
+
+namespace asio {
+
+/// Provides raw-oriented socket functionality.
+/**
+ * The basic_raw_socket class template provides asynchronous and blocking
+ * raw-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol,
+    typename RawSocketService = raw_socket_service<Protocol> >
+class basic_raw_socket
+  : public basic_socket<Protocol, RawSocketService>
+{
+public:
+  /// The native representation of a socket.
+  typedef typename RawSocketService::native_type native_type;
+
+  /// The protocol type.
+  typedef Protocol protocol_type;
+
+  /// The endpoint type.
+  typedef typename Protocol::endpoint endpoint_type;
+
+  /// Construct a basic_raw_socket without opening it.
+  /**
+   * This constructor creates a raw socket without opening it. The open()
+   * function must be called before data can be sent or received on the socket.
+   *
+   * @param io_service The io_service object that the raw socket will use
+   * to dispatch handlers for any asynchronous operations performed on the
+   * socket.
+   */
+  explicit basic_raw_socket(asio::io_service& io_service)
+    : basic_socket<Protocol, RawSocketService>(io_service)
+  {
+  }
+
+  /// Construct and open a basic_raw_socket.
+  /**
+   * This constructor creates and opens a raw socket.
+   *
+   * @param io_service The io_service object that the raw 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_raw_socket(asio::io_service& io_service,
+      const protocol_type& protocol)
+    : basic_socket<Protocol, RawSocketService>(io_service, protocol)
+  {
+  }
+
+  /// Construct a basic_raw_socket, opening it and binding it to the given
+  /// local endpoint.
+  /**
+   * This constructor creates a raw 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 raw 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 raw
+   * socket will be bound.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  basic_raw_socket(asio::io_service& io_service,
+      const endpoint_type& endpoint)
+    : basic_socket<Protocol, RawSocketService>(io_service, endpoint)
+  {
+  }
+
+  /// Construct a basic_raw_socket on an existing native socket.
+  /**
+   * This constructor creates a raw socket object to hold an existing
+   * native socket.
+   *
+   * @param io_service The io_service object that the raw 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_raw_socket(asio::io_service& io_service,
+      const protocol_type& protocol, const native_type& native_socket)
+    : basic_socket<Protocol, RawSocketService>(
+        io_service, protocol, native_socket)
+  {
+  }
+
+  /// Send some data on a connected socket.
+  /**
+   * This function is used to send data on the raw socket. The function call
+   * will block until the data has been sent successfully or an error occurs.
+   *
+   * @param buffers One ore more data buffers to be sent on the socket.
+   *
+   * @returns The number of bytes sent.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note The send operation can only be used with a connected socket. Use
+   * the send_to function to send data on an unconnected raw socket.
+   *
+   * @par Example
+   * To send a single data buffer use the @ref buffer function as follows:
+   * @code socket.send(asio::buffer(data, size)); @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)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Send some data on a connected socket.
+  /**
+   * This function is used to send data on the raw socket. The function call
+   * will block until the data has been sent successfully or an error occurs.
+   *
+   * @param buffers One ore 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.
+   *
+   * @note The send operation can only be used with a connected socket. Use
+   * the send_to function to send data on an unconnected raw socket.
+   */
+  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 a connected socket.
+  /**
+   * This function is used to send data on the raw socket. The function call
+   * will block until the data has been sent successfully or an 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.
+   *
+   * @note The send operation can only be used with a connected socket. Use
+   * the send_to function to send data on an unconnected raw socket.
+   */
+  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 on a connected socket.
+  /**
+   * This function is used to send data on the raw socket. The function call
+   * will block until the data has been sent successfully or an error occurs.
+   *
+   * @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 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().
+   *
+   * @note The async_send operation can only be used with a connected socket.
+   * Use the async_send_to function to send data on an unconnected raw
+   * socket.
+   *
+   * @par Example
+   * To send a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.async_send(asio::buffer(data, size), 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, WriteHandler handler)
+  {
+    this->service.async_send(this->implementation, buffers, 0, handler);
+  }
+
+  /// Start an asynchronous send on a connected socket.
+  /**
+   * This function is used to send data on the raw socket. The function call
+   * will block until the data has been sent successfully or an error occurs.
+   *
+   * @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().
+   *
+   * @note The async_send operation can only be used with a connected socket.
+   * Use the async_send_to function to send data on an unconnected raw
+   * socket.
+   */
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_send(const ConstBufferSequence& buffers,
+      socket_base::message_flags flags, WriteHandler handler)
+  {
+    this->service.async_send(this->implementation, buffers, flags, handler);
+  }
+
+  /// Send raw data to the specified endpoint.
+  /**
+   * This function is used to send raw data to the specified remote endpoint.
+   * The function call will block until the data has been sent successfully or
+   * an error occurs.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   *
+   * @param destination The remote endpoint to which the data will be sent.
+   *
+   * @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
+   * asio::ip::udp::endpoint destination(
+   *     asio::ip::address::from_string("1.2.3.4"), 12345);
+   * socket.send_to(asio::buffer(data, size), destination);
+   * @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_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send_to(
+        this->implementation, buffers, destination, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Send raw data to the specified endpoint.
+  /**
+   * This function is used to send raw data to the specified remote endpoint.
+   * The function call will block until the data has been sent successfully or
+   * an error occurs.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   *
+   * @param destination The remote endpoint to which the data will be sent.
+   *
+   * @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.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t send_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, socket_base::message_flags flags)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send_to(
+        this->implementation, buffers, destination, flags, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Send raw data to the specified endpoint.
+  /**
+   * This function is used to send raw data to the specified remote endpoint.
+   * The function call will block until the data has been sent successfully or
+   * an error occurs.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   *
+   * @param destination The remote endpoint to which the data will be sent.
+   *
+   * @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.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t send_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, socket_base::message_flags flags,
+      asio::error_code& ec)
+  {
+    return this->service.send_to(this->implementation,
+        buffers, destination, flags, ec);
+  }
+
+  /// Start an asynchronous send.
+  /**
+   * This function is used to asynchronously send raw data to the specified
+   * remote endpoint. The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   * 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 destination The remote endpoint to which the data will be sent.
+   * Copies will be made of the endpoint as required.
+   *
+   * @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
+   * asio::ip::udp::endpoint destination(
+   *     asio::ip::address::from_string("1.2.3.4"), 12345);
+   * socket.async_send_to(
+   *     asio::buffer(data, size), destination, 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_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, WriteHandler handler)
+  {
+    this->service.async_send_to(this->implementation, buffers, destination, 0,
+        handler);
+  }
+
+  /// Start an asynchronous send.
+  /**
+   * This function is used to asynchronously send raw data to the specified
+   * remote endpoint. The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be sent to the remote endpoint.
+   * 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 destination The remote endpoint to which the data will be sent.
+   * Copies will be made of the endpoint as required.
+   *
+   * @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().
+   */
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_send_to(const ConstBufferSequence& buffers,
+      const endpoint_type& destination, socket_base::message_flags flags,
+      WriteHandler handler)
+  {
+    this->service.async_send_to(this->implementation, buffers, destination,
+        flags, handler);
+  }
+
+  /// Receive some data on a connected socket.
+  /**
+   * This function is used to receive data on the raw socket. The function
+   * call will block until data has been received successfully or an error
+   * occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note The receive operation can only be used with a connected socket. Use
+   * the receive_from function to receive data on an unconnected raw
+   * socket.
+   *
+   * @par Example
+   * To receive into a single data buffer use the @ref buffer function as
+   * follows:
+   * @code socket.receive(asio::buffer(data, size)); @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)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive(
+        this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Receive some data on a connected socket.
+  /**
+   * This function is used to receive data on the raw socket. The function
+   * call will block until data has been received successfully or an error
+   * occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note The receive operation can only be used with a connected socket. Use
+   * the receive_from function to receive data on an unconnected raw
+   * socket.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive(const MutableBufferSequence& buffers,
+      socket_base::message_flags flags)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive(
+        this->implementation, buffers, 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 raw socket. The function
+   * call will block until data has been received successfully or an error
+   * occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes received.
+   *
+   * @note The receive operation can only be used with a connected socket. Use
+   * the receive_from function to receive data on an unconnected raw
+   * socket.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive(const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    return this->service.receive(this->implementation, buffers, flags, ec);
+  }
+
+  /// Start an asynchronous receive on a connected socket.
+  /**
+   * This function is used to asynchronously receive data from the raw
+   * 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 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().
+   *
+   * @note The async_receive operation can only be used with a connected socket.
+   * Use the async_receive_from function to receive data on an unconnected
+   * raw socket.
+   *
+   * @par Example
+   * To receive into a single data buffer use the @ref buffer function as
+   * follows:
+   * @code
+   * socket.async_receive(asio::buffer(data, size), 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, ReadHandler handler)
+  {
+    this->service.async_receive(this->implementation, buffers, 0, handler);
+  }
+
+  /// Start an asynchronous receive on a connected socket.
+  /**
+   * This function is used to asynchronously receive data from the raw
+   * 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 flags Flags specifying how the receive call is to be made.
+   *
+   * @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().
+   *
+   * @note The async_receive operation can only be used with a connected socket.
+   * Use the async_receive_from function to receive data on an unconnected
+   * raw socket.
+   */
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_receive(const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, ReadHandler handler)
+  {
+    this->service.async_receive(this->implementation, buffers, flags, handler);
+  }
+
+  /// Receive raw data with the endpoint of the sender.
+  /**
+   * This function is used to receive raw data. The function call will block
+   * until data has been received successfully or an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the data.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * To receive into a single data buffer use the @ref buffer function as
+   * follows:
+   * @code
+   * asio::ip::udp::endpoint sender_endpoint;
+   * socket.receive_from(
+   *     asio::buffer(data, size), sender_endpoint);
+   * @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_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive_from(
+        this->implementation, buffers, sender_endpoint, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+  
+  /// Receive raw data with the endpoint of the sender.
+  /**
+   * This function is used to receive raw data. The function call will block
+   * until data has been received successfully or an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the data.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @returns The number of bytes received.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, socket_base::message_flags flags)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive_from(
+        this->implementation, buffers, sender_endpoint, flags, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+  
+  /// Receive raw data with the endpoint of the sender.
+  /**
+   * This function is used to receive raw data. The function call will block
+   * until data has been received successfully or an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the data.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes received.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t receive_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, socket_base::message_flags flags,
+      asio::error_code& ec)
+  {
+    return this->service.receive_from(this->implementation, buffers,
+        sender_endpoint, flags, ec);
+  }
+
+  /// Start an asynchronous receive.
+  /**
+   * This function is used to asynchronously receive raw data. 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 sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the data. Ownership of the sender_endpoint object
+   * is retained by the caller, which must guarantee that it is 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_from(
+   *     asio::buffer(data, size), 0, sender_endpoint, 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_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, ReadHandler handler)
+  {
+    this->service.async_receive_from(this->implementation, buffers,
+        sender_endpoint, 0, handler);
+  }
+
+  /// Start an asynchronous receive.
+  /**
+   * This function is used to asynchronously receive raw data. 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 sender_endpoint An endpoint object that receives the endpoint of
+   * the remote sender of the data. Ownership of the sender_endpoint object
+   * is retained by the caller, which must guarantee that it is valid until the
+   * handler is called.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @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().
+   */
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_receive_from(const MutableBufferSequence& buffers,
+      endpoint_type& sender_endpoint, socket_base::message_flags flags,
+      ReadHandler handler)
+  {
+    this->service.async_receive_from(this->implementation, buffers,
+        sender_endpoint, flags, handler);
+  }
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_RAW_SOCKET_HPP

+ 622 - 0
ext/asio/asio/basic_serial_port.hpp

@@ -0,0 +1,622 @@
+//
+// basic_serial_port.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.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_SERIAL_PORT_HPP
+#define ASIO_BASIC_SERIAL_PORT_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 <string>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_io_object.hpp"
+#include "asio/error.hpp"
+#include "asio/serial_port_base.hpp"
+#include "asio/serial_port_service.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#if defined(ASIO_HAS_SERIAL_PORT) \
+  || defined(GENERATING_DOCUMENTATION)
+
+namespace asio {
+
+/// Provides serial port functionality.
+/**
+ * The basic_serial_port class template provides functionality that is common
+ * to all serial ports.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename SerialPortService = serial_port_service>
+class basic_serial_port
+  : public basic_io_object<SerialPortService>,
+    public serial_port_base
+{
+public:
+  /// The native representation of a serial port.
+  typedef typename SerialPortService::native_type native_type;
+
+  /// A basic_serial_port is always the lowest layer.
+  typedef basic_serial_port<SerialPortService> lowest_layer_type;
+
+  /// Construct a basic_serial_port without opening it.
+  /**
+   * This constructor creates a serial port without opening it.
+   *
+   * @param io_service The io_service object that the serial port will use to
+   * dispatch handlers for any asynchronous operations performed on the port.
+   */
+  explicit basic_serial_port(asio::io_service& io_service)
+    : basic_io_object<SerialPortService>(io_service)
+  {
+  }
+
+  /// Construct and open a basic_serial_port.
+  /**
+   * This constructor creates and opens a serial port for the specified device
+   * name.
+   *
+   * @param io_service The io_service object that the serial port will use to
+   * dispatch handlers for any asynchronous operations performed on the port.
+   *
+   * @param device The platform-specific device name for this serial
+   * port.
+   */
+  explicit basic_serial_port(asio::io_service& io_service,
+      const char* device)
+    : basic_io_object<SerialPortService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.open(this->implementation, device, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Construct and open a basic_serial_port.
+  /**
+   * This constructor creates and opens a serial port for the specified device
+   * name.
+   *
+   * @param io_service The io_service object that the serial port will use to
+   * dispatch handlers for any asynchronous operations performed on the port.
+   *
+   * @param device The platform-specific device name for this serial
+   * port.
+   */
+  explicit basic_serial_port(asio::io_service& io_service,
+      const std::string& device)
+    : basic_io_object<SerialPortService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.open(this->implementation, device, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Construct a basic_serial_port on an existing native serial port.
+  /**
+   * This constructor creates a serial port object to hold an existing native
+   * serial port.
+   *
+   * @param io_service The io_service object that the serial port will use to
+   * dispatch handlers for any asynchronous operations performed on the port.
+   *
+   * @param native_serial_port A native serial port.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  basic_serial_port(asio::io_service& io_service,
+      const native_type& native_serial_port)
+    : basic_io_object<SerialPortService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.assign(this->implementation, native_serial_port, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Get a reference to the lowest layer.
+  /**
+   * This function returns a reference to the lowest layer in a stack of
+   * layers. Since a basic_serial_port cannot contain any further layers, it
+   * simply returns a reference to itself.
+   *
+   * @return A reference to the lowest layer in the stack of layers. Ownership
+   * is not transferred to the caller.
+   */
+  lowest_layer_type& lowest_layer()
+  {
+    return *this;
+  }
+
+  /// Get a const reference to the lowest layer.
+  /**
+   * This function returns a const reference to the lowest layer in a stack of
+   * layers. Since a basic_serial_port cannot contain any further layers, it
+   * simply returns a reference to itself.
+   *
+   * @return A const reference to the lowest layer in the stack of layers.
+   * Ownership is not transferred to the caller.
+   */
+  const lowest_layer_type& lowest_layer() const
+  {
+    return *this;
+  }
+
+  /// Open the serial port using the specified device name.
+  /**
+   * This function opens the serial port for the specified device name.
+   *
+   * @param device The platform-specific device name.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void open(const std::string& device)
+  {
+    asio::error_code ec;
+    this->service.open(this->implementation, device, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Open the serial port using the specified device name.
+  /**
+   * This function opens the serial port using the given platform-specific
+   * device name.
+   *
+   * @param device The platform-specific device name.
+   *
+   * @param ec Set the indicate what error occurred, if any.
+   */
+  asio::error_code open(const std::string& device,
+      asio::error_code& ec)
+  {
+    return this->service.open(this->implementation, device, ec);
+  }
+
+  /// Assign an existing native serial port to the serial port.
+  /*
+   * This function opens the serial port to hold an existing native serial port.
+   *
+   * @param native_serial_port A native serial port.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void assign(const native_type& native_serial_port)
+  {
+    asio::error_code ec;
+    this->service.assign(this->implementation, native_serial_port, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Assign an existing native serial port to the serial port.
+  /*
+   * This function opens the serial port to hold an existing native serial port.
+   *
+   * @param native_serial_port A native serial port.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  asio::error_code assign(const native_type& native_serial_port,
+      asio::error_code& ec)
+  {
+    return this->service.assign(this->implementation, native_serial_port, ec);
+  }
+
+  /// Determine whether the serial port is open.
+  bool is_open() const
+  {
+    return this->service.is_open(this->implementation);
+  }
+
+  /// Close the serial port.
+  /**
+   * This function is used to close the serial port. Any asynchronous read or
+   * write operations will be cancelled immediately, and will complete with the
+   * asio::error::operation_aborted error.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void close()
+  {
+    asio::error_code ec;
+    this->service.close(this->implementation, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Close the serial port.
+  /**
+   * This function is used to close the serial port. Any asynchronous read or
+   * write operations will be cancelled immediately, and will complete with the
+   * asio::error::operation_aborted error.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  asio::error_code close(asio::error_code& ec)
+  {
+    return this->service.close(this->implementation, ec);
+  }
+
+  /// Get the native serial port representation.
+  /**
+   * This function may be used to obtain the underlying representation of the
+   * serial port. This is intended to allow access to native serial port
+   * functionality that is not otherwise provided.
+   */
+  native_type native()
+  {
+    return this->service.native(this->implementation);
+  }
+
+  /// Cancel all asynchronous operations associated with the serial port.
+  /**
+   * This function causes all outstanding asynchronous read or write operations
+   * to finish immediately, and the handlers for cancelled operations will be
+   * passed the asio::error::operation_aborted error.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void cancel()
+  {
+    asio::error_code ec;
+    this->service.cancel(this->implementation, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Cancel all asynchronous operations associated with the serial port.
+  /**
+   * This function causes all outstanding asynchronous read or write operations
+   * to finish immediately, and the handlers for cancelled operations will be
+   * passed the asio::error::operation_aborted error.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  asio::error_code cancel(asio::error_code& ec)
+  {
+    return this->service.cancel(this->implementation, ec);
+  }
+
+  /// Send a break sequence to the serial port.
+  /**
+   * This function causes a break sequence of platform-specific duration to be
+   * sent out the serial port.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void send_break()
+  {
+    asio::error_code ec;
+    this->service.send_break(this->implementation, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Send a break sequence to the serial port.
+  /**
+   * This function causes a break sequence of platform-specific duration to be
+   * sent out the serial port.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  asio::error_code send_break(asio::error_code& ec)
+  {
+    return this->service.send_break(this->implementation, ec);
+  }
+
+  /// Set an option on the serial port.
+  /**
+   * This function is used to set an option on the serial port.
+   *
+   * @param option The option value to be set on the serial port.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @sa SettableSerialPortOption @n
+   * asio::serial_port_base::baud_rate @n
+   * asio::serial_port_base::flow_control @n
+   * asio::serial_port_base::parity @n
+   * asio::serial_port_base::stop_bits @n
+   * asio::serial_port_base::character_size
+   */
+  template <typename SettableSerialPortOption>
+  void set_option(const SettableSerialPortOption& option)
+  {
+    asio::error_code ec;
+    this->service.set_option(this->implementation, option, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Set an option on the serial port.
+  /**
+   * This function is used to set an option on the serial port.
+   *
+   * @param option The option value to be set on the serial port.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @sa SettableSerialPortOption @n
+   * asio::serial_port_base::baud_rate @n
+   * asio::serial_port_base::flow_control @n
+   * asio::serial_port_base::parity @n
+   * asio::serial_port_base::stop_bits @n
+   * asio::serial_port_base::character_size
+   */
+  template <typename SettableSerialPortOption>
+  asio::error_code set_option(const SettableSerialPortOption& option,
+      asio::error_code& ec)
+  {
+    return this->service.set_option(this->implementation, option, ec);
+  }
+
+  /// Get an option from the serial port.
+  /**
+   * This function is used to get the current value of an option on the serial
+   * port.
+   *
+   * @param option The option value to be obtained from the serial port.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @sa GettableSerialPortOption @n
+   * asio::serial_port_base::baud_rate @n
+   * asio::serial_port_base::flow_control @n
+   * asio::serial_port_base::parity @n
+   * asio::serial_port_base::stop_bits @n
+   * asio::serial_port_base::character_size
+   */
+  template <typename GettableSerialPortOption>
+  void get_option(GettableSerialPortOption& option)
+  {
+    asio::error_code ec;
+    this->service.get_option(this->implementation, option, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Get an option from the serial port.
+  /**
+   * This function is used to get the current value of an option on the serial
+   * port.
+   *
+   * @param option The option value to be obtained from the serial port.
+   *
+   * @param ec Set to indicate what error occured, if any.
+   *
+   * @sa GettableSerialPortOption @n
+   * asio::serial_port_base::baud_rate @n
+   * asio::serial_port_base::flow_control @n
+   * asio::serial_port_base::parity @n
+   * asio::serial_port_base::stop_bits @n
+   * asio::serial_port_base::character_size
+   */
+  template <typename GettableSerialPortOption>
+  asio::error_code get_option(GettableSerialPortOption& option,
+      asio::error_code& ec)
+  {
+    return this->service.get_option(this->implementation, option, ec);
+  }
+
+  /// Write some data to the serial port.
+  /**
+   * This function is used to write data to the serial port. The function call
+   * will block until one or more bytes of the data has been written
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more data buffers to be written to the serial port.
+   *
+   * @returns The number of bytes written.
+   *
+   * @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 write_some 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.
+   *
+   * @par Example
+   * To write a single data buffer use the @ref buffer function as follows:
+   * @code
+   * serial_port.write_some(asio::buffer(data, size));
+   * @endcode
+   * See the @ref buffer documentation for information on writing multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.write_some(this->implementation, buffers, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Write some data to the serial port.
+  /**
+   * This function is used to write data to the serial port. The function call
+   * will block until one or more bytes of the data has been written
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more data buffers to be written to the serial port.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes written. Returns 0 if an error occurred.
+   *
+   * @note The write_some 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 write_some(const ConstBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return this->service.write_some(this->implementation, buffers, ec);
+  }
+
+  /// Start an asynchronous write.
+  /**
+   * This function is used to asynchronously write data to the serial port.
+   * The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be written to the serial port.
+   * 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 handler The handler to be called when the write 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 written.
+   * ); @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().
+   *
+   * @note The write operation may not transmit all of the data to the peer.
+   * Consider using the @ref async_write function if you need to ensure that all
+   * data is written before the asynchronous operation completes.
+   *
+   * @par Example
+   * To write a single data buffer use the @ref buffer function as follows:
+   * @code
+   * serial_port.async_write_some(asio::buffer(data, size), handler);
+   * @endcode
+   * See the @ref buffer documentation for information on writing multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_write_some(const ConstBufferSequence& buffers,
+      WriteHandler handler)
+  {
+    this->service.async_write_some(this->implementation, buffers, handler);
+  }
+
+  /// Read some data from the serial port.
+  /**
+   * This function is used to read data from the serial port. The function
+   * call will block until one or more bytes of data has been read successfully,
+   * or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   *
+   * @returns The number of bytes read.
+   *
+   * @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 read_some operation may not read 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 read into a single data buffer use the @ref buffer function as follows:
+   * @code
+   * serial_port.read_some(asio::buffer(data, size));
+   * @endcode
+   * See the @ref buffer documentation for information on reading into multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.read_some(this->implementation, buffers, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Read some data from the serial port.
+  /**
+   * This function is used to read data from the serial port. The function
+   * call will block until one or more bytes of data has been read successfully,
+   * or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes read. Returns 0 if an error occurred.
+   *
+   * @note The read_some operation may not read 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 read_some(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return this->service.read_some(this->implementation, buffers, ec);
+  }
+
+  /// Start an asynchronous read.
+  /**
+   * This function is used to asynchronously read data from the serial port.
+   * The function call always returns immediately.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   * 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 handler The handler to be called when the read 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 read.
+   * ); @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().
+   *
+   * @note The read operation may not read all of the requested number of bytes.
+   * Consider using the @ref async_read function if you need to ensure that the
+   * requested amount of data is read before the asynchronous operation
+   * completes.
+   *
+   * @par Example
+   * To read into a single data buffer use the @ref buffer function as follows:
+   * @code
+   * serial_port.async_read_some(asio::buffer(data, size), handler);
+   * @endcode
+   * See the @ref buffer documentation for information on reading 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_read_some(const MutableBufferSequence& buffers,
+      ReadHandler handler)
+  {
+    this->service.async_read_some(this->implementation, buffers, handler);
+  }
+};
+
+} // namespace asio
+
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+       //   || defined(GENERATING_DOCUMENTATION)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_SERIAL_PORT_HPP

File diff suppressed because it is too large
+ 1063 - 0
ext/asio/asio/basic_socket.hpp


+ 824 - 0
ext/asio/asio/basic_socket_acceptor.hpp

@@ -0,0 +1,824 @@
+//
+// basic_socket_acceptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SOCKET_ACCEPTOR_HPP
+#define ASIO_BASIC_SOCKET_ACCEPTOR_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/basic_io_object.hpp"
+#include "asio/basic_socket.hpp"
+#include "asio/error.hpp"
+#include "asio/socket_acceptor_service.hpp"
+#include "asio/socket_base.hpp"
+#include "asio/detail/throw_error.hpp"
+
+namespace asio {
+
+/// Provides the ability to accept new connections.
+/**
+ * The basic_socket_acceptor class template is used for accepting new socket
+ * connections.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * Opening a socket acceptor with the SO_REUSEADDR option enabled:
+ * @code
+ * asio::ip::tcp::acceptor acceptor(io_service);
+ * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen();
+ * @endcode
+ */
+template <typename Protocol,
+    typename SocketAcceptorService = socket_acceptor_service<Protocol> >
+class basic_socket_acceptor
+  : public basic_io_object<SocketAcceptorService>,
+    public socket_base
+{
+public:
+  /// The native representation of an acceptor.
+  typedef typename SocketAcceptorService::native_type native_type;
+
+  /// The protocol type.
+  typedef Protocol protocol_type;
+
+  /// The endpoint type.
+  typedef typename Protocol::endpoint endpoint_type;
+
+  /// Construct an acceptor without opening it.
+  /**
+   * This constructor creates an acceptor without opening it to listen for new
+   * connections. The open() function must be called before the acceptor can
+   * accept new socket connections.
+   *
+   * @param io_service The io_service object that the acceptor will use to
+   * dispatch handlers for any asynchronous operations performed on the
+   * acceptor.
+   */
+  explicit basic_socket_acceptor(asio::io_service& io_service)
+    : basic_io_object<SocketAcceptorService>(io_service)
+  {
+  }
+
+  /// Construct an open acceptor.
+  /**
+   * This constructor creates an acceptor and automatically opens it.
+   *
+   * @param io_service The io_service object that the acceptor will use to
+   * dispatch handlers for any asynchronous operations performed on the
+   * acceptor.
+   *
+   * @param protocol An object specifying protocol parameters to be used.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  basic_socket_acceptor(asio::io_service& io_service,
+      const protocol_type& protocol)
+    : basic_io_object<SocketAcceptorService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.open(this->implementation, protocol, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Construct an acceptor opened on the given endpoint.
+  /**
+   * This constructor creates an acceptor and automatically opens it to listen
+   * for new connections on the specified endpoint.
+   *
+   * @param io_service The io_service object that the acceptor will use to
+   * dispatch handlers for any asynchronous operations performed on the
+   * acceptor.
+   *
+   * @param endpoint An endpoint on the local machine on which the acceptor
+   * will listen for new connections.
+   *
+   * @param reuse_addr Whether the constructor should set the socket option
+   * socket_base::reuse_address.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @note This constructor is equivalent to the following code:
+   * @code
+   * basic_socket_acceptor<Protocol> acceptor(io_service);
+   * acceptor.open(endpoint.protocol());
+   * if (reuse_addr)
+   *   acceptor.set_option(socket_base::reuse_address(true));
+   * acceptor.bind(endpoint);
+   * acceptor.listen(listen_backlog);
+   * @endcode
+   */
+  basic_socket_acceptor(asio::io_service& io_service,
+      const endpoint_type& endpoint, bool reuse_addr = true)
+    : basic_io_object<SocketAcceptorService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.open(this->implementation, endpoint.protocol(), ec);
+    asio::detail::throw_error(ec);
+    if (reuse_addr)
+    {
+      this->service.set_option(this->implementation,
+          socket_base::reuse_address(true), ec);
+      asio::detail::throw_error(ec);
+    }
+    this->service.bind(this->implementation, endpoint, ec);
+    asio::detail::throw_error(ec);
+    this->service.listen(this->implementation,
+        socket_base::max_connections, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Construct a basic_socket_acceptor on an existing native acceptor.
+  /**
+   * This constructor creates an acceptor object to hold an existing native
+   * acceptor.
+   *
+   * @param io_service The io_service object that the acceptor will use to
+   * dispatch handlers for any asynchronous operations performed on the
+   * acceptor.
+   *
+   * @param protocol An object specifying protocol parameters to be used.
+   *
+   * @param native_acceptor A native acceptor.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  basic_socket_acceptor(asio::io_service& io_service,
+      const protocol_type& protocol, const native_type& native_acceptor)
+    : basic_io_object<SocketAcceptorService>(io_service)
+  {
+    asio::error_code ec;
+    this->service.assign(this->implementation, protocol, native_acceptor, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Open the acceptor using the specified protocol.
+  /**
+   * This function opens the socket acceptor so that it will use the specified
+   * protocol.
+   *
+   * @param protocol An object specifying which protocol is to be used.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * acceptor.open(asio::ip::tcp::v4());
+   * @endcode
+   */
+  void open(const protocol_type& protocol = protocol_type())
+  {
+    asio::error_code ec;
+    this->service.open(this->implementation, protocol, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Open the acceptor using the specified protocol.
+  /**
+   * This function opens the socket acceptor so that it will use the specified
+   * protocol.
+   *
+   * @param protocol An object specifying which protocol is to be used.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * asio::error_code ec;
+   * acceptor.open(asio::ip::tcp::v4(), ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  asio::error_code open(const protocol_type& protocol,
+      asio::error_code& ec)
+  {
+    return this->service.open(this->implementation, protocol, ec);
+  }
+
+  /// Assigns an existing native acceptor to the acceptor.
+  /*
+   * This function opens the acceptor to hold an existing native acceptor.
+   *
+   * @param protocol An object specifying which protocol is to be used.
+   *
+   * @param native_acceptor A native acceptor.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void assign(const protocol_type& protocol, const native_type& native_acceptor)
+  {
+    asio::error_code ec;
+    this->service.assign(this->implementation, protocol, native_acceptor, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Assigns an existing native acceptor to the acceptor.
+  /*
+   * This function opens the acceptor to hold an existing native acceptor.
+   *
+   * @param protocol An object specifying which protocol is to be used.
+   *
+   * @param native_acceptor A native acceptor.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  asio::error_code assign(const protocol_type& protocol,
+      const native_type& native_acceptor, asio::error_code& ec)
+  {
+    return this->service.assign(this->implementation,
+        protocol, native_acceptor, ec);
+  }
+
+  /// Determine whether the acceptor is open.
+  bool is_open() const
+  {
+    return this->service.is_open(this->implementation);
+  }
+
+  /// Bind the acceptor to the given local endpoint.
+  /**
+   * This function binds the socket acceptor to the specified endpoint on the
+   * local machine.
+   *
+   * @param endpoint An endpoint on the local machine to which the socket
+   * acceptor will be bound.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * acceptor.open(asio::ip::tcp::v4());
+   * acceptor.bind(asio::ip::tcp::endpoint(12345));
+   * @endcode
+   */
+  void bind(const endpoint_type& endpoint)
+  {
+    asio::error_code ec;
+    this->service.bind(this->implementation, endpoint, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Bind the acceptor to the given local endpoint.
+  /**
+   * This function binds the socket acceptor to the specified endpoint on the
+   * local machine.
+   *
+   * @param endpoint An endpoint on the local machine to which the socket
+   * acceptor will be bound.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * acceptor.open(asio::ip::tcp::v4());
+   * asio::error_code ec;
+   * acceptor.bind(asio::ip::tcp::endpoint(12345), ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  asio::error_code bind(const endpoint_type& endpoint,
+      asio::error_code& ec)
+  {
+    return this->service.bind(this->implementation, endpoint, ec);
+  }
+
+  /// Place the acceptor into the state where it will listen for new
+  /// connections.
+  /**
+   * This function puts the socket acceptor into the state where it may accept
+   * new connections.
+   *
+   * @param backlog The maximum length of the queue of pending connections.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void listen(int backlog = socket_base::max_connections)
+  {
+    asio::error_code ec;
+    this->service.listen(this->implementation, backlog, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Place the acceptor into the state where it will listen for new
+  /// connections.
+  /**
+   * This function puts the socket acceptor into the state where it may accept
+   * new connections.
+   *
+   * @param backlog The maximum length of the queue of pending connections.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::error_code ec;
+   * acceptor.listen(asio::socket_base::max_connections, ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  asio::error_code listen(int backlog, asio::error_code& ec)
+  {
+    return this->service.listen(this->implementation, backlog, ec);
+  }
+
+  /// Close the acceptor.
+  /**
+   * This function is used to close the acceptor. Any asynchronous accept
+   * operations will be cancelled immediately.
+   *
+   * A subsequent call to open() is required before the acceptor can again be
+   * used to again perform socket accept operations.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void close()
+  {
+    asio::error_code ec;
+    this->service.close(this->implementation, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Close the acceptor.
+  /**
+   * This function is used to close the acceptor. Any asynchronous accept
+   * operations will be cancelled immediately.
+   *
+   * A subsequent call to open() is required before the acceptor can again be
+   * used to again perform socket accept operations.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::error_code ec;
+   * acceptor.close(ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  asio::error_code close(asio::error_code& ec)
+  {
+    return this->service.close(this->implementation, ec);
+  }
+
+  /// Get the native acceptor representation.
+  /**
+   * This function may be used to obtain the underlying representation of the
+   * acceptor. This is intended to allow access to native acceptor functionality
+   * that is not otherwise provided.
+   */
+  native_type native()
+  {
+    return this->service.native(this->implementation);
+  }
+
+  /// Cancel all asynchronous operations associated with the acceptor.
+  /**
+   * This function causes all outstanding asynchronous connect, send and receive
+   * operations to finish immediately, and the handlers for cancelled operations
+   * will be passed the asio::error::operation_aborted error.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  void cancel()
+  {
+    asio::error_code ec;
+    this->service.cancel(this->implementation, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Cancel all asynchronous operations associated with the acceptor.
+  /**
+   * This function causes all outstanding asynchronous connect, send and receive
+   * operations to finish immediately, and the handlers for cancelled operations
+   * will be passed the asio::error::operation_aborted error.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   */
+  asio::error_code cancel(asio::error_code& ec)
+  {
+    return this->service.cancel(this->implementation, ec);
+  }
+
+  /// Set an option on the acceptor.
+  /**
+   * This function is used to set an option on the acceptor.
+   *
+   * @param option The new option value to be set on the acceptor.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @sa SettableSocketOption @n
+   * asio::socket_base::reuse_address
+   * asio::socket_base::enable_connection_aborted
+   *
+   * @par Example
+   * Setting the SOL_SOCKET/SO_REUSEADDR option:
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::acceptor::reuse_address option(true);
+   * acceptor.set_option(option);
+   * @endcode
+   */
+  template <typename SettableSocketOption>
+  void set_option(const SettableSocketOption& option)
+  {
+    asio::error_code ec;
+    this->service.set_option(this->implementation, option, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Set an option on the acceptor.
+  /**
+   * This function is used to set an option on the acceptor.
+   *
+   * @param option The new option value to be set on the acceptor.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @sa SettableSocketOption @n
+   * asio::socket_base::reuse_address
+   * asio::socket_base::enable_connection_aborted
+   *
+   * @par Example
+   * Setting the SOL_SOCKET/SO_REUSEADDR option:
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::acceptor::reuse_address option(true);
+   * asio::error_code ec;
+   * acceptor.set_option(option, ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  template <typename SettableSocketOption>
+  asio::error_code set_option(const SettableSocketOption& option,
+      asio::error_code& ec)
+  {
+    return this->service.set_option(this->implementation, option, ec);
+  }
+
+  /// Get an option from the acceptor.
+  /**
+   * This function is used to get the current value of an option on the
+   * acceptor.
+   *
+   * @param option The option value to be obtained from the acceptor.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @sa GettableSocketOption @n
+   * asio::socket_base::reuse_address
+   *
+   * @par Example
+   * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::acceptor::reuse_address option;
+   * acceptor.get_option(option);
+   * bool is_set = option.get();
+   * @endcode
+   */
+  template <typename GettableSocketOption>
+  void get_option(GettableSocketOption& option)
+  {
+    asio::error_code ec;
+    this->service.get_option(this->implementation, option, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Get an option from the acceptor.
+  /**
+   * This function is used to get the current value of an option on the
+   * acceptor.
+   *
+   * @param option The option value to be obtained from the acceptor.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @sa GettableSocketOption @n
+   * asio::socket_base::reuse_address
+   *
+   * @par Example
+   * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::acceptor::reuse_address option;
+   * asio::error_code ec;
+   * acceptor.get_option(option, ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * bool is_set = option.get();
+   * @endcode
+   */
+  template <typename GettableSocketOption>
+  asio::error_code get_option(GettableSocketOption& option,
+      asio::error_code& ec)
+  {
+    return this->service.get_option(this->implementation, option, ec);
+  }
+
+  /// Get the local endpoint of the acceptor.
+  /**
+   * This function is used to obtain the locally bound endpoint of the acceptor.
+   *
+   * @returns An object that represents the local endpoint of the acceptor.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
+   * @endcode
+   */
+  endpoint_type local_endpoint() const
+  {
+    asio::error_code ec;
+    endpoint_type ep = this->service.local_endpoint(this->implementation, ec);
+    asio::detail::throw_error(ec);
+    return ep;
+  }
+
+  /// Get the local endpoint of the acceptor.
+  /**
+   * This function is used to obtain the locally bound endpoint of the acceptor.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns An object that represents the local endpoint of the acceptor.
+   * Returns a default-constructed endpoint object if an error occurred and the
+   * error handler did not throw an exception.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::error_code ec;
+   * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  endpoint_type local_endpoint(asio::error_code& ec) const
+  {
+    return this->service.local_endpoint(this->implementation, ec);
+  }
+
+  /// Accept a new connection.
+  /**
+   * This function is used to accept a new connection from a peer into the
+   * given socket. The function call will block until a new connection has been
+   * accepted successfully or an error occurs.
+   *
+   * @param peer The socket into which the new connection will be accepted.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::socket socket(io_service);
+   * acceptor.accept(socket);
+   * @endcode
+   */
+  template <typename SocketService>
+  void accept(basic_socket<protocol_type, SocketService>& peer)
+  {
+    asio::error_code ec;
+    this->service.accept(this->implementation, peer, 0, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Accept a new connection.
+  /**
+   * This function is used to accept a new connection from a peer into the
+   * given socket. The function call will block until a new connection has been
+   * accepted successfully or an error occurs.
+   *
+   * @param peer The socket into which the new connection will be accepted.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::soocket socket(io_service);
+   * asio::error_code ec;
+   * acceptor.accept(socket, ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  template <typename SocketService>
+  asio::error_code accept(
+      basic_socket<protocol_type, SocketService>& peer,
+      asio::error_code& ec)
+  {
+    return this->service.accept(this->implementation, peer, 0, ec);
+  }
+
+  /// Start an asynchronous accept.
+  /**
+   * This function is used to asynchronously accept a new connection into a
+   * socket. The function call always returns immediately.
+   *
+   * @param peer The socket into which the new connection will be accepted.
+   * Ownership of the peer object is retained by the caller, which must
+   * guarantee that it is valid until the handler is called.
+   *
+   * @param handler The handler to be called when the accept 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.
+   * ); @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
+   * @code
+   * void accept_handler(const asio::error_code& error)
+   * {
+   *   if (!error)
+   *   {
+   *     // Accept succeeded.
+   *   }
+   * }
+   *
+   * ...
+   *
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::socket socket(io_service);
+   * acceptor.async_accept(socket, accept_handler);
+   * @endcode
+   */
+  template <typename SocketService, typename AcceptHandler>
+  void async_accept(basic_socket<protocol_type, SocketService>& peer,
+      AcceptHandler handler)
+  {
+    this->service.async_accept(this->implementation, peer, 0, handler);
+  }
+
+  /// Accept a new connection and obtain the endpoint of the peer
+  /**
+   * This function is used to accept a new connection from a peer into the
+   * given socket, and additionally provide the endpoint of the remote peer.
+   * The function call will block until a new connection has been accepted
+   * successfully or an error occurs.
+   *
+   * @param peer The socket into which the new connection will be accepted.
+   *
+   * @param peer_endpoint An endpoint object which will receive the endpoint of
+   * the remote peer.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::socket socket(io_service);
+   * asio::ip::tcp::endpoint endpoint;
+   * acceptor.accept(socket, endpoint);
+   * @endcode
+   */
+  template <typename SocketService>
+  void accept(basic_socket<protocol_type, SocketService>& peer,
+      endpoint_type& peer_endpoint)
+  {
+    asio::error_code ec;
+    this->service.accept(this->implementation, peer, &peer_endpoint, ec);
+    asio::detail::throw_error(ec);
+  }
+
+  /// Accept a new connection and obtain the endpoint of the peer
+  /**
+   * This function is used to accept a new connection from a peer into the
+   * given socket, and additionally provide the endpoint of the remote peer.
+   * The function call will block until a new connection has been accepted
+   * successfully or an error occurs.
+   *
+   * @param peer The socket into which the new connection will be accepted.
+   *
+   * @param peer_endpoint An endpoint object which will receive the endpoint of
+   * the remote peer.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::socket socket(io_service);
+   * asio::ip::tcp::endpoint endpoint;
+   * asio::error_code ec;
+   * acceptor.accept(socket, endpoint, ec);
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  template <typename SocketService>
+  asio::error_code accept(
+      basic_socket<protocol_type, SocketService>& peer,
+      endpoint_type& peer_endpoint, asio::error_code& ec)
+  {
+    return this->service.accept(this->implementation, peer, &peer_endpoint, ec);
+  }
+
+  /// Start an asynchronous accept.
+  /**
+   * This function is used to asynchronously accept a new connection into a
+   * socket, and additionally obtain the endpoint of the remote peer. The
+   * function call always returns immediately.
+   *
+   * @param peer The socket into which the new connection will be accepted.
+   * Ownership of the peer object is retained by the caller, which must
+   * guarantee that it is valid until the handler is called.
+   *
+   * @param peer_endpoint An endpoint object into which the endpoint of the
+   * remote peer will be written. Ownership of the peer_endpoint object is
+   * retained by the caller, which must guarantee that it is valid until the
+   * handler is called.
+   *
+   * @param handler The handler to be called when the accept 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.
+   * ); @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().
+   */
+  template <typename SocketService, typename AcceptHandler>
+  void async_accept(basic_socket<protocol_type, SocketService>& peer,
+      endpoint_type& peer_endpoint, AcceptHandler handler)
+  {
+    this->service.async_accept(this->implementation,
+        peer, &peer_endpoint, handler);
+  }
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP

+ 156 - 0
ext/asio/asio/basic_socket_iostream.hpp

@@ -0,0 +1,156 @@
+//
+// basic_socket_iostream.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SOCKET_IOSTREAM_HPP
+#define ASIO_BASIC_SOCKET_IOSTREAM_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/push_options.hpp"
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/utility/base_from_member.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_socket_streambuf.hpp"
+#include "asio/stream_socket_service.hpp"
+
+#if !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY)
+#define ASIO_SOCKET_IOSTREAM_MAX_ARITY 5
+#endif // !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY)
+
+// A macro that should expand to:
+//   template <typename T1, ..., typename Tn>
+//   explicit basic_socket_iostream(T1 x1, ..., Tn xn)
+//     : basic_iostream<char>(&this->boost::base_from_member<
+//         basic_socket_streambuf<Protocol, StreamSocketService> >::member)
+//   {
+//     if (rdbuf()->connect(x1, ..., xn) == 0)
+//       this->setstate(std::ios_base::failbit);
+//   }
+// This macro should only persist within this file.
+
+#define ASIO_PRIVATE_CTR_DEF(z, n, data) \
+  template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
+  explicit basic_socket_iostream(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
+    : std::basic_iostream<char>(&this->boost::base_from_member< \
+        basic_socket_streambuf<Protocol, StreamSocketService> >::member) \
+  { \
+    tie(this); \
+    if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
+      this->setstate(std::ios_base::failbit); \
+  } \
+  /**/
+
+// A macro that should expand to:
+//   template <typename T1, ..., typename Tn>
+//   void connect(T1 x1, ..., Tn xn)
+//   {
+//     if (rdbuf()->connect(x1, ..., xn) == 0)
+//       this->setstate(std::ios_base::failbit);
+//   }
+// This macro should only persist within this file.
+
+#define ASIO_PRIVATE_CONNECT_DEF(z, n, data) \
+  template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
+  void connect(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
+  { \
+    if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
+      this->setstate(std::ios_base::failbit); \
+  } \
+  /**/
+
+namespace asio {
+
+/// Iostream interface for a socket.
+template <typename Protocol,
+    typename StreamSocketService = stream_socket_service<Protocol> >
+class basic_socket_iostream
+  : public boost::base_from_member<
+      basic_socket_streambuf<Protocol, StreamSocketService> >,
+    public std::basic_iostream<char>
+{
+public:
+  /// Construct a basic_socket_iostream without establishing a connection.
+  basic_socket_iostream()
+    : std::basic_iostream<char>(&this->boost::base_from_member<
+        basic_socket_streambuf<Protocol, StreamSocketService> >::member)
+  {
+    tie(this);
+  }
+
+#if defined(GENERATING_DOCUMENTATION)
+  /// Establish a connection to an endpoint corresponding to a resolver query.
+  /**
+   * This constructor automatically establishes a connection based on the
+   * supplied resolver query parameters. The arguments are used to construct
+   * a resolver query object.
+   */
+  template <typename T1, ..., typename TN>
+  explicit basic_socket_iostream(T1 t1, ..., TN tn);
+#else
+  BOOST_PP_REPEAT_FROM_TO(
+      1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY),
+      ASIO_PRIVATE_CTR_DEF, _ )
+#endif
+
+#if defined(GENERATING_DOCUMENTATION)
+  /// Establish a connection to an endpoint corresponding to a resolver query.
+  /**
+   * This function automatically establishes a connection based on the supplied
+   * resolver query parameters. The arguments are used to construct a resolver
+   * query object.
+   */
+  template <typename T1, ..., typename TN>
+  void connect(T1 t1, ..., TN tn);
+#else
+  BOOST_PP_REPEAT_FROM_TO(
+      1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY),
+      ASIO_PRIVATE_CONNECT_DEF, _ )
+#endif
+
+  /// Close the connection.
+  void close()
+  {
+    if (rdbuf()->close() == 0)
+      this->setstate(std::ios_base::failbit);
+  }
+
+  /// Return a pointer to the underlying streambuf.
+  basic_socket_streambuf<Protocol, StreamSocketService>* rdbuf() const
+  {
+    return const_cast<basic_socket_streambuf<Protocol, StreamSocketService>*>(
+        &this->boost::base_from_member<
+          basic_socket_streambuf<Protocol, StreamSocketService> >::member);
+  }
+};
+
+} // namespace asio
+
+#undef ASIO_PRIVATE_CTR_DEF
+#undef ASIO_PRIVATE_CONNECT_DEF
+
+#endif // defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP

+ 295 - 0
ext/asio/asio/basic_socket_streambuf.hpp

@@ -0,0 +1,295 @@
+//
+// basic_socket_streambuf.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SOCKET_STREAMBUF_HPP
+#define ASIO_BASIC_SOCKET_STREAMBUF_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/push_options.hpp"
+#include <streambuf>
+#include <boost/array.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/utility/base_from_member.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_socket.hpp"
+#include "asio/io_service.hpp"
+#include "asio/stream_socket_service.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#if !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
+#define ASIO_SOCKET_STREAMBUF_MAX_ARITY 5
+#endif // !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
+
+// A macro that should expand to:
+//   template <typename T1, ..., typename Tn>
+//   basic_socket_streambuf<Protocol, StreamSocketService>* connect(
+//       T1 x1, ..., Tn xn)
+//   {
+//     init_buffers();
+//     asio::error_code ec;
+//     this->basic_socket<Protocol, StreamSocketService>::close(ec);
+//     typedef typename Protocol::resolver resolver_type;
+//     typedef typename resolver_type::query resolver_query;
+//     resolver_query query(x1, ..., xn);
+//     resolve_and_connect(query, ec);
+//     return !ec ? this : 0;
+//   }
+// This macro should only persist within this file.
+
+#define ASIO_PRIVATE_CONNECT_DEF( z, n, data ) \
+  template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
+  basic_socket_streambuf<Protocol, StreamSocketService>* connect( \
+      BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
+  { \
+    init_buffers(); \
+    asio::error_code ec; \
+    this->basic_socket<Protocol, StreamSocketService>::close(ec); \
+    typedef typename Protocol::resolver resolver_type; \
+    typedef typename resolver_type::query resolver_query; \
+    resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \
+    resolve_and_connect(query, ec); \
+    return !ec ? this : 0; \
+  } \
+  /**/
+
+namespace asio {
+
+/// Iostream streambuf for a socket.
+template <typename Protocol,
+    typename StreamSocketService = stream_socket_service<Protocol> >
+class basic_socket_streambuf
+  : public std::streambuf,
+    private boost::base_from_member<io_service>,
+    public basic_socket<Protocol, StreamSocketService>
+{
+public:
+  /// The endpoint type.
+  typedef typename Protocol::endpoint endpoint_type;
+
+  /// Construct a basic_socket_streambuf without establishing a connection.
+  basic_socket_streambuf()
+    : basic_socket<Protocol, StreamSocketService>(
+        boost::base_from_member<asio::io_service>::member),
+      unbuffered_(false)
+  {
+    init_buffers();
+  }
+
+  /// Destructor flushes buffered data.
+  virtual ~basic_socket_streambuf()
+  {
+    if (pptr() != pbase())
+      overflow(traits_type::eof());
+  }
+
+  /// Establish a connection.
+  /**
+   * This function establishes a connection to the specified endpoint.
+   *
+   * @return \c this if a connection was successfully established, a null
+   * pointer otherwise.
+   */
+  basic_socket_streambuf<Protocol, StreamSocketService>* connect(
+      const endpoint_type& endpoint)
+  {
+    init_buffers();
+    asio::error_code ec;
+    this->basic_socket<Protocol, StreamSocketService>::close(ec);
+    this->basic_socket<Protocol, StreamSocketService>::connect(endpoint, ec);
+    return !ec ? this : 0;
+  }
+
+#if defined(GENERATING_DOCUMENTATION)
+  /// Establish a connection.
+  /**
+   * This function automatically establishes a connection based on the supplied
+   * resolver query parameters. The arguments are used to construct a resolver
+   * query object.
+   *
+   * @return \c this if a connection was successfully established, a null
+   * pointer otherwise.
+   */
+  template <typename T1, ..., typename TN>
+  basic_socket_streambuf<Protocol, StreamSocketService>* connect(
+      T1 t1, ..., TN tn);
+#else
+  BOOST_PP_REPEAT_FROM_TO(
+      1, BOOST_PP_INC(ASIO_SOCKET_STREAMBUF_MAX_ARITY),
+      ASIO_PRIVATE_CONNECT_DEF, _ )
+#endif
+
+  /// Close the connection.
+  /**
+   * @return \c this if a connection was successfully established, a null
+   * pointer otherwise.
+   */
+  basic_socket_streambuf<Protocol, StreamSocketService>* close()
+  {
+    asio::error_code ec;
+    sync();
+    this->basic_socket<Protocol, StreamSocketService>::close(ec);
+    if (!ec)
+      init_buffers();
+    return !ec ? this : 0;
+  }
+
+protected:
+  int_type underflow()
+  {
+    if (gptr() == egptr())
+    {
+      asio::error_code ec;
+      std::size_t bytes_transferred = this->service.receive(
+          this->implementation,
+          asio::buffer(asio::buffer(get_buffer_) + putback_max),
+          0, ec);
+      if (ec)
+        return traits_type::eof();
+      setg(get_buffer_.begin(), get_buffer_.begin() + putback_max,
+          get_buffer_.begin() + putback_max + bytes_transferred);
+      return traits_type::to_int_type(*gptr());
+    }
+    else
+    {
+      return traits_type::eof();
+    }
+  }
+
+  int_type overflow(int_type c)
+  {
+    if (unbuffered_)
+    {
+      if (traits_type::eq_int_type(c, traits_type::eof()))
+      {
+        // Nothing to do.
+        return traits_type::not_eof(c);
+      }
+      else
+      {
+        // Send the single character immediately.
+        asio::error_code ec;
+        char_type ch = traits_type::to_char_type(c);
+        this->service.send(this->implementation,
+            asio::buffer(&ch, sizeof(char_type)), 0, ec);
+        if (ec)
+          return traits_type::eof();
+        return c;
+      }
+    }
+    else
+    {
+      // Send all data in the output buffer.
+      asio::const_buffer buffer =
+        asio::buffer(pbase(), pptr() - pbase());
+      while (asio::buffer_size(buffer) > 0)
+      {
+        asio::error_code ec;
+        std::size_t bytes_transferred = this->service.send(
+            this->implementation, asio::buffer(buffer),
+            0, ec);
+        if (ec)
+          return traits_type::eof();
+        buffer = buffer + bytes_transferred;
+      }
+      setp(put_buffer_.begin(), put_buffer_.end());
+
+      // If the new character is eof then our work here is done.
+      if (traits_type::eq_int_type(c, traits_type::eof()))
+        return traits_type::not_eof(c);
+
+      // Add the new character to the output buffer.
+      *pptr() = traits_type::to_char_type(c);
+      pbump(1);
+      return c;
+    }
+  }
+
+  int sync()
+  {
+    return overflow(traits_type::eof());
+  }
+
+  std::streambuf* setbuf(char_type* s, std::streamsize n)
+  {
+    if (pptr() == pbase() && s == 0 && n == 0)
+    {
+      unbuffered_ = true;
+      setp(0, 0);
+      return this;
+    }
+
+    return 0;
+  }
+
+private:
+  void init_buffers()
+  {
+    setg(get_buffer_.begin(),
+        get_buffer_.begin() + putback_max,
+        get_buffer_.begin() + putback_max);
+    if (unbuffered_)
+      setp(0, 0);
+    else
+      setp(put_buffer_.begin(), put_buffer_.end());
+  }
+
+  template <typename ResolverQuery>
+  void resolve_and_connect(const ResolverQuery& query,
+      asio::error_code& ec)
+  {
+    typedef typename Protocol::resolver resolver_type;
+    typedef typename resolver_type::iterator iterator_type;
+    resolver_type resolver(
+        boost::base_from_member<asio::io_service>::member);
+    iterator_type i = resolver.resolve(query, ec);
+    if (!ec)
+    {
+      iterator_type end;
+      ec = asio::error::host_not_found;
+      while (ec && i != end)
+      {
+        this->basic_socket<Protocol, StreamSocketService>::close();
+        this->basic_socket<Protocol, StreamSocketService>::connect(*i, ec);
+        ++i;
+      }
+    }
+  }
+
+  enum { putback_max = 8 };
+  enum { buffer_size = 512 };
+  boost::array<char, buffer_size> get_buffer_;
+  boost::array<char, buffer_size> put_buffer_;
+  bool unbuffered_;
+};
+
+} // namespace asio
+
+#undef ASIO_PRIVATE_CONNECT_DEF
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP

+ 718 - 0
ext/asio/asio/basic_stream_socket.hpp

@@ -0,0 +1,718 @@
+//
+// basic_stream_socket.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_STREAM_SOCKET_HPP
+#define ASIO_BASIC_STREAM_SOCKET_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_socket.hpp"
+#include "asio/error.hpp"
+#include "asio/stream_socket_service.hpp"
+#include "asio/detail/throw_error.hpp"
+
+namespace asio {
+
+/// Provides stream-oriented socket functionality.
+/**
+ * The basic_stream_socket class template provides asynchronous and blocking
+ * stream-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Protocol,
+    typename StreamSocketService = stream_socket_service<Protocol> >
+class basic_stream_socket
+  : public basic_socket<Protocol, StreamSocketService>
+{
+public:
+  /// The native representation of a socket.
+  typedef typename StreamSocketService::native_type native_type;
+
+  /// The protocol type.
+  typedef Protocol protocol_type;
+
+  /// The endpoint type.
+  typedef typename Protocol::endpoint endpoint_type;
+
+  /// Construct a basic_stream_socket without opening it.
+  /**
+   * This constructor creates a stream 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 stream socket will use to
+   * dispatch handlers for any asynchronous operations performed on the socket.
+   */
+  explicit basic_stream_socket(asio::io_service& io_service)
+    : basic_socket<Protocol, StreamSocketService>(io_service)
+  {
+  }
+
+  /// Construct and open a basic_stream_socket.
+  /**
+   * This constructor creates and opens a stream 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 stream 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_stream_socket(asio::io_service& io_service,
+      const protocol_type& protocol)
+    : basic_socket<Protocol, StreamSocketService>(io_service, protocol)
+  {
+  }
+
+  /// Construct a basic_stream_socket, opening it and binding it to the given
+  /// local endpoint.
+  /**
+   * This constructor creates a stream 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 stream 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 stream
+   * socket will be bound.
+   *
+   * @throws asio::system_error Thrown on failure.
+   */
+  basic_stream_socket(asio::io_service& io_service,
+      const endpoint_type& endpoint)
+    : basic_socket<Protocol, StreamSocketService>(io_service, endpoint)
+  {
+  }
+
+  /// Construct a basic_stream_socket on an existing native socket.
+  /**
+   * This constructor creates a stream socket object to hold an existing native
+   * socket.
+   *
+   * @param io_service The io_service object that the stream 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_stream_socket(asio::io_service& io_service,
+      const protocol_type& protocol, const native_type& native_socket)
+    : basic_socket<Protocol, StreamSocketService>(
+        io_service, protocol, native_socket)
+  {
+  }
+
+  /// Send some data on the socket.
+  /**
+   * This function is used to send data on the stream socket. The function
+   * call will block until one or more bytes of the data has been sent
+   * successfully, or an until error occurs.
+   *
+   * @param buffers One or more data buffers to be sent on the socket.
+   *
+   * @returns The number of bytes sent.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @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.
+   *
+   * @par Example
+   * To send a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.send(asio::buffer(data, size));
+   * @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)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send(
+        this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Send some data on the socket.
+  /**
+   * This function is used to send data on the stream socket. The function
+   * call will block until one or more bytes of 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.
+   *
+   * @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.
+   *
+   * @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 stream socket. The function
+   * call will block until one or more bytes of 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 stream 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 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().
+   *
+   * @note The send operation may not transmit all of the data to the peer.
+   * Consider using the @ref async_write function if you need to ensure that all
+   * data is written before the asynchronous operation completes.
+   *
+   * @par Example
+   * To send a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.async_send(asio::buffer(data, size), 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, WriteHandler handler)
+  {
+    this->service.async_send(this->implementation, buffers, 0, handler);
+  }
+
+  /// Start an asynchronous send.
+  /**
+   * This function is used to asynchronously send data on the stream 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().
+   *
+   * @note The send operation may not transmit all of the data to the peer.
+   * Consider using the @ref async_write function if you need to ensure that all
+   * data is written before the asynchronous operation completes.
+   *
+   * @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)
+  {
+    this->service.async_send(this->implementation, buffers, flags, handler);
+  }
+
+  /// Receive some data on the socket.
+  /**
+   * This function is used to receive data on the stream socket. The function
+   * call will block until one or more bytes of data has been received
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @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));
+   * @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)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Receive some data on the socket.
+  /**
+   * This function is used to receive data on the stream socket. The function
+   * call will block until one or more bytes of data has been received
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @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);
+   * @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 flags)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive(
+        this->implementation, buffers, 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 stream socket. The function
+   * call will block until one or more bytes of data has been received
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be received.
+   *
+   * @param flags Flags specifying how the receive call is to be made.
+   *
+   * @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 flags, asio::error_code& ec)
+  {
+    return this->service.receive(this->implementation, buffers, flags, ec);
+  }
+
+  /// Start an asynchronous receive.
+  /**
+   * This function is used to asynchronously receive data from the stream
+   * 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 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().
+   *
+   * @note The receive operation may not receive all of the requested number of
+   * bytes. Consider using the @ref async_read function if you need to ensure
+   * that the requested amount of data is received before the asynchronous
+   * operation completes.
+   *
+   * @par Example
+   * To receive into a single data buffer use the @ref buffer function as
+   * follows:
+   * @code
+   * socket.async_receive(asio::buffer(data, size), 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, ReadHandler handler)
+  {
+    this->service.async_receive(this->implementation, buffers, 0, handler);
+  }
+
+  /// Start an asynchronous receive.
+  /**
+   * This function is used to asynchronously receive data from the stream
+   * 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 flags Flags specifying how the receive call is to be made.
+   *
+   * @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().
+   *
+   * @note The receive operation may not receive all of the requested number of
+   * bytes. Consider using the @ref async_read function if you need to ensure
+   * that the requested amount of data is received before the asynchronous
+   * operation completes.
+   *
+   * @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, 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 flags, ReadHandler handler)
+  {
+    this->service.async_receive(this->implementation, buffers, flags, handler);
+  }
+
+  /// Write some data to the socket.
+  /**
+   * This function is used to write data to the stream socket. The function call
+   * will block until one or more bytes of the data has been written
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more data buffers to be written to the socket.
+   *
+   * @returns The number of bytes written.
+   *
+   * @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 write_some 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.
+   *
+   * @par Example
+   * To write a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.write_some(asio::buffer(data, size));
+   * @endcode
+   * See the @ref buffer documentation for information on writing multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Write some data to the socket.
+  /**
+   * This function is used to write data to the stream socket. The function call
+   * will block until one or more bytes of the data has been written
+   * successfully, or until an error occurs.
+   *
+   * @param buffers One or more data buffers to be written to the socket.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes written. Returns 0 if an error occurred.
+   *
+   * @note The write_some 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 write_some(const ConstBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return this->service.send(this->implementation, buffers, 0, ec);
+  }
+
+  /// Start an asynchronous write.
+  /**
+   * This function is used to asynchronously write data to the stream socket.
+   * The function call always returns immediately.
+   *
+   * @param buffers One or more data buffers to be written to 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 handler The handler to be called when the write 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 written.
+   * ); @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().
+   *
+   * @note The write operation may not transmit all of the data to the peer.
+   * Consider using the @ref async_write function if you need to ensure that all
+   * data is written before the asynchronous operation completes.
+   *
+   * @par Example
+   * To write a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.async_write_some(asio::buffer(data, size), handler);
+   * @endcode
+   * See the @ref buffer documentation for information on writing multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_write_some(const ConstBufferSequence& buffers,
+      WriteHandler handler)
+  {
+    this->service.async_send(this->implementation, buffers, 0, handler);
+  }
+
+  /// Read some data from the socket.
+  /**
+   * This function is used to read data from the stream socket. The function
+   * call will block until one or more bytes of data has been read successfully,
+   * or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   *
+   * @returns The number of bytes read.
+   *
+   * @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 read_some operation may not read 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 read into a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.read_some(asio::buffer(data, size));
+   * @endcode
+   * See the @ref buffer documentation for information on reading into multiple
+   * buffers in one go, and how to use it with arrays, boost::array or
+   * std::vector.
+   */
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers)
+  {
+    asio::error_code ec;
+    std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
+    asio::detail::throw_error(ec);
+    return s;
+  }
+
+  /// Read some data from the socket.
+  /**
+   * This function is used to read data from the stream socket. The function
+   * call will block until one or more bytes of data has been read successfully,
+   * or until an error occurs.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns The number of bytes read. Returns 0 if an error occurred.
+   *
+   * @note The read_some operation may not read 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 read_some(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return this->service.receive(this->implementation, buffers, 0, ec);
+  }
+
+  /// Start an asynchronous read.
+  /**
+   * This function is used to asynchronously read data from the stream socket.
+   * The function call always returns immediately.
+   *
+   * @param buffers One or more buffers into which the data will be read.
+   * 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 handler The handler to be called when the read 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 read.
+   * ); @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().
+   *
+   * @note The read operation may not read all of the requested number of bytes.
+   * Consider using the @ref async_read function if you need to ensure that the
+   * requested amount of data is read before the asynchronous operation
+   * completes.
+   *
+   * @par Example
+   * To read into a single data buffer use the @ref buffer function as follows:
+   * @code
+   * socket.async_read_some(asio::buffer(data, size), handler);
+   * @endcode
+   * See the @ref buffer documentation for information on reading 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_read_some(const MutableBufferSequence& buffers,
+      ReadHandler handler)
+  {
+    this->service.async_receive(this->implementation, buffers, 0, handler);
+  }
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BASIC_STREAM_SOCKET_HPP

+ 348 - 0
ext/asio/asio/basic_streambuf.hpp

@@ -0,0 +1,348 @@
+//
+// basic_streambuf.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_STREAMBUF_HPP
+#define ASIO_BASIC_STREAMBUF_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/push_options.hpp"
+#include <algorithm>
+#include <cstring>
+#include <memory>
+#include <stdexcept>
+#include <streambuf>
+#include <vector>
+#include <boost/limits.hpp>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/buffer.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+
+/// Automatically resizable buffer class based on std::streambuf.
+/**
+ * The @c basic_streambuf class is derived from @c std::streambuf to associate
+ * the streambuf's input and output sequences with one or more character
+ * arrays. These character arrays are internal to the @c basic_streambuf
+ * object, but direct access to the array elements is provided to permit them
+ * to be used efficiently with I/O operations. Characters written to the output
+ * sequence of a @c basic_streambuf object are appended to the input sequence
+ * of the same object.
+ *
+ * The @c basic_streambuf class's public interface is intended to permit the
+ * following implementation strategies:
+ *
+ * @li A single contiguous character array, which is reallocated as necessary
+ * to accommodate changes in the size of the character sequence. This is the
+ * implementation approach currently used in Asio.
+ *
+ * @li A sequence of one or more character arrays, where each array is of the
+ * same size. Additional character array objects are appended to the sequence
+ * to accommodate changes in the size of the character sequence.
+ *
+ * @li A sequence of one or more character arrays of varying sizes. Additional
+ * character array objects are appended to the sequence to accommodate changes
+ * in the size of the character sequence.
+ *
+ * The constructor for basic_streambuf accepts a @c size_t argument specifying
+ * the maximum of the sum of the sizes of the input sequence and output
+ * sequence. During the lifetime of the @c basic_streambuf object, the following
+ * invariant holds:
+ * @code size() <= max_size()@endcode
+ * Any member function that would, if successful, cause the invariant to be
+ * violated shall throw an exception of class @c std::length_error.
+ *
+ * The constructor for @c basic_streambuf takes an Allocator argument. A copy
+ * of this argument is used for any memory allocation performed, by the
+ * constructor and by all member functions, during the lifetime of each @c
+ * basic_streambuf object.
+ *
+ * @par Examples
+ * Writing directly from an streambuf to a socket:
+ * @code
+ * asio::streambuf b;
+ * std::ostream os(&b);
+ * os << "Hello, World!\n";
+ *
+ * // try sending some data in input sequence
+ * size_t n = sock.send(b.data());
+ *
+ * b.consume(n); // sent data is removed from input sequence
+ * @endcode
+ *
+ * Reading from a socket directly into a streambuf:
+ * @code
+ * asio::streambuf b;
+ *
+ * // reserve 512 bytes in output sequence
+ * asio::streambuf::mutable_buffers_type bufs = b.prepare(512);
+ *
+ * size_t n = sock.receive(bufs);
+ *
+ * // received data is "committed" from output sequence to input sequence
+ * b.commit(n);
+ *
+ * std::istream is(&b);
+ * std::string s;
+ * is >> s;
+ * @endcode
+ */
+template <typename Allocator = std::allocator<char> >
+class basic_streambuf
+  : public std::streambuf,
+    private noncopyable
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+  /// The type used to represent the input sequence as a list of buffers.
+  typedef implementation_defined const_buffers_type;
+
+  /// The type used to represent the output sequence as a list of buffers.
+  typedef implementation_defined mutable_buffers_type;
+#else
+  typedef asio::const_buffers_1 const_buffers_type;
+  typedef asio::mutable_buffers_1 mutable_buffers_type;
+#endif
+
+  /// Construct a basic_streambuf object.
+  /**
+   * Constructs a streambuf with the specified maximum size. The initial size
+   * of the streambuf's input sequence is 0.
+   */
+  explicit basic_streambuf(
+      std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
+      const Allocator& allocator = Allocator())
+    : max_size_(max_size),
+      buffer_(allocator)
+  {
+    std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
+    buffer_.resize((std::max<std::size_t>)(pend, 1));
+    setg(&buffer_[0], &buffer_[0], &buffer_[0]);
+    setp(&buffer_[0], &buffer_[0] + pend);
+  }
+
+  /// Get the size of the input sequence.
+  /**
+   * @returns The size of the input sequence. The value is equal to that
+   * calculated for @c s in the following code:
+   * @code
+   * size_t s = 0;
+   * const_buffers_type bufs = data();
+   * const_buffers_type::const_iterator i = bufs.begin();
+   * while (i != bufs.end())
+   * {
+   *   const_buffer buf(*i++);
+   *   s += buffer_size(buf);
+   * }
+   * @endcode
+   */
+  std::size_t size() const
+  {
+    return pptr() - gptr();
+  }
+
+  /// Get the maximum size of the basic_streambuf.
+  /**
+   * @returns The allowed maximum of the sum of the sizes of the input sequence
+   * and output sequence.
+   */
+  std::size_t max_size() const
+  {
+    return max_size_;
+  }
+
+  /// Get a list of buffers that represents the input sequence.
+  /**
+   * @returns An object of type @c const_buffers_type that satisfies
+   * ConstBufferSequence requirements, representing all character arrays in the
+   * input sequence.
+   *
+   * @note The returned object is invalidated by any @c basic_streambuf member
+   * function that modifies the input sequence or output sequence.
+   */
+  const_buffers_type data() const
+  {
+    return asio::buffer(asio::const_buffer(gptr(),
+          (pptr() - gptr()) * sizeof(char_type)));
+  }
+
+  /// Get a list of buffers that represents the output sequence, with the given
+  /// size.
+  /**
+   * Ensures that the output sequence can accommodate @c n characters,
+   * reallocating character array objects as necessary.
+   *
+   * @returns An object of type @c mutable_buffers_type that satisfies
+   * MutableBufferSequence requirements, representing character array objects
+   * at the start of the output sequence such that the sum of the buffer sizes
+   * is @c n.
+   *
+   * @throws std::length_error If <tt>size() + n > max_size()</tt>.
+   *
+   * @note The returned object is invalidated by any @c basic_streambuf member
+   * function that modifies the input sequence or output sequence.
+   */
+  mutable_buffers_type prepare(std::size_t n)
+  {
+    reserve(n);
+    return asio::buffer(asio::mutable_buffer(
+          pptr(), n * sizeof(char_type)));
+  }
+
+  /// Move characters from the output sequence to the input sequence.
+  /**
+   * Appends @c n characters from the start of the output sequence to the input
+   * sequence. The beginning of the output sequence is advanced by @c n
+   * characters.
+   *
+   * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
+   * no intervening operations that modify the input or output sequence.
+   *
+   * @throws std::length_error If @c n is greater than the size of the output
+   * sequence.
+   */
+  void commit(std::size_t n)
+  {
+    if (pptr() + n > epptr())
+      n = epptr() - pptr();
+    pbump(static_cast<int>(n));
+    setg(eback(), gptr(), pptr());
+  }
+
+  /// Remove characters from the input sequence.
+  /**
+   * Removes @c n characters from the beginning of the input sequence.
+   *
+   * @throws std::length_error If <tt>n > size()</tt>.
+   */
+  void consume(std::size_t n)
+  {
+    if (gptr() + n > pptr())
+      n = pptr() - gptr();
+    gbump(static_cast<int>(n));
+  }
+
+protected:
+  enum { buffer_delta = 128 };
+
+  /// Override std::streambuf behaviour.
+  /**
+   * Behaves according to the specification of @c std::streambuf::underflow().
+   */
+  int_type underflow()
+  {
+    if (gptr() < pptr())
+    {
+      setg(&buffer_[0], gptr(), pptr());
+      return traits_type::to_int_type(*gptr());
+    }
+    else
+    {
+      return traits_type::eof();
+    }
+  }
+
+  /// Override std::streambuf behaviour.
+  /**
+   * Behaves according to the specification of @c std::streambuf::overflow(),
+   * with the specialisation that @c std::length_error is thrown if appending
+   * the character to the input sequence would require the condition
+   * <tt>size() > max_size()</tt> to be true.
+   */
+  int_type overflow(int_type c)
+  {
+    if (!traits_type::eq_int_type(c, traits_type::eof()))
+    {
+      if (pptr() == epptr())
+      {
+        std::size_t buffer_size = pptr() - gptr();
+        if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
+        {
+          reserve(max_size_ - buffer_size);
+        }
+        else
+        {
+          reserve(buffer_delta);
+        }
+      }
+
+      *pptr() = traits_type::to_char_type(c);
+      pbump(1);
+      return c;
+    }
+
+    return traits_type::not_eof(c);
+  }
+
+  void reserve(std::size_t n)
+  {
+    // Get current stream positions as offsets.
+    std::size_t gnext = gptr() - &buffer_[0];
+    std::size_t pnext = pptr() - &buffer_[0];
+    std::size_t pend = epptr() - &buffer_[0];
+
+    // Check if there is already enough space in the put area.
+    if (n <= pend - pnext)
+    {
+      return;
+    }
+
+    // Shift existing contents of get area to start of buffer.
+    if (gnext > 0)
+    {
+      pnext -= gnext;
+      std::memmove(&buffer_[0], &buffer_[0] + gnext, pnext);
+    }
+
+    // Ensure buffer is large enough to hold at least the specified size.
+    if (n > pend - pnext)
+    {
+      if (n <= max_size_ && pnext <= max_size_ - n)
+      {
+        pend = pnext + n;
+        buffer_.resize((std::max<std::size_t>)(pend, 1));
+      }
+      else
+      {
+        std::length_error ex("asio::streambuf too long");
+        boost::throw_exception(ex);
+      }
+    }
+
+    // Update stream positions.
+    setg(&buffer_[0], &buffer_[0], &buffer_[0] + pnext);
+    setp(&buffer_[0] + pnext, &buffer_[0] + pend);
+  }
+
+private:
+  std::size_t max_size_;
+  std::vector<char_type, Allocator> buffer_;
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_BASIC_STREAMBUF_HPP

File diff suppressed because it is too large
+ 1040 - 0
ext/asio/asio/buffer.hpp


+ 461 - 0
ext/asio/asio/buffered_read_stream.hpp

@@ -0,0 +1,461 @@
+//
+// buffered_read_stream.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERED_READ_STREAM_HPP
+#define ASIO_BUFFERED_READ_STREAM_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 <cstddef>
+#include <cstring>
+#include <boost/config.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/buffered_read_stream_fwd.hpp"
+#include "asio/buffer.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_resize_guard.hpp"
+#include "asio/detail/buffered_stream_storage.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+
+/// Adds buffering to the read-related operations of a stream.
+/**
+ * The buffered_read_stream class template can be used to add buffering to the
+ * synchronous and asynchronous read operations of a stream.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, Sync_Read_Stream, SyncWriteStream.
+ */
+template <typename Stream>
+class buffered_read_stream
+  : private noncopyable
+{
+public:
+  /// The type of the next layer.
+  typedef typename boost::remove_reference<Stream>::type next_layer_type;
+
+  /// The type of the lowest layer.
+  typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+
+#if defined(GENERATING_DOCUMENTATION)
+  /// The default buffer size.
+  static const std::size_t default_buffer_size = implementation_defined;
+#else
+  BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
+#endif
+
+  /// Construct, passing the specified argument to initialise the next layer.
+  template <typename Arg>
+  explicit buffered_read_stream(Arg& a)
+    : next_layer_(a),
+      storage_(default_buffer_size)
+  {
+  }
+
+  /// Construct, passing the specified argument to initialise the next layer.
+  template <typename Arg>
+  buffered_read_stream(Arg& a, std::size_t buffer_size)
+    : next_layer_(a),
+      storage_(buffer_size)
+  {
+  }
+
+  /// Get a reference to the next layer.
+  next_layer_type& next_layer()
+  {
+    return next_layer_;
+  }
+
+  /// Get a reference to the lowest layer.
+  lowest_layer_type& lowest_layer()
+  {
+    return next_layer_.lowest_layer();
+  }
+
+  /// Get a const reference to the lowest layer.
+  const lowest_layer_type& lowest_layer() const
+  {
+    return next_layer_.lowest_layer();
+  }
+
+  /// (Deprecated: use get_io_service().) Get the io_service associated with
+  /// the object.
+  asio::io_service& io_service()
+  {
+    return next_layer_.get_io_service();
+  }
+
+  /// Get the io_service associated with the object.
+  asio::io_service& get_io_service()
+  {
+    return next_layer_.get_io_service();
+  }
+
+  /// Close the stream.
+  void close()
+  {
+    next_layer_.close();
+  }
+
+  /// Close the stream.
+  asio::error_code close(asio::error_code& ec)
+  {
+    return next_layer_.close(ec);
+  }
+
+  /// Write the given data to the stream. Returns the number of bytes written.
+  /// Throws an exception on failure.
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers)
+  {
+    return next_layer_.write_some(buffers);
+  }
+
+  /// Write the given data to the stream. Returns the number of bytes written,
+  /// or 0 if an error occurred.
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return next_layer_.write_some(buffers, ec);
+  }
+
+  /// Start an asynchronous write. The data being written must be valid for the
+  /// lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_write_some(const ConstBufferSequence& buffers,
+      WriteHandler handler)
+  {
+    next_layer_.async_write_some(buffers, handler);
+  }
+
+  /// Fill the buffer with some data. Returns the number of bytes placed in the
+  /// buffer as a result of the operation. Throws an exception on failure.
+  std::size_t fill()
+  {
+    detail::buffer_resize_guard<detail::buffered_stream_storage>
+      resize_guard(storage_);
+    std::size_t previous_size = storage_.size();
+    storage_.resize(storage_.capacity());
+    storage_.resize(previous_size + next_layer_.read_some(buffer(
+            storage_.data() + previous_size,
+            storage_.size() - previous_size)));
+    resize_guard.commit();
+    return storage_.size() - previous_size;
+  }
+
+  /// Fill the buffer with some data. Returns the number of bytes placed in the
+  /// buffer as a result of the operation, or 0 if an error occurred.
+  std::size_t fill(asio::error_code& ec)
+  {
+    detail::buffer_resize_guard<detail::buffered_stream_storage>
+      resize_guard(storage_);
+    std::size_t previous_size = storage_.size();
+    storage_.resize(storage_.capacity());
+    storage_.resize(previous_size + next_layer_.read_some(buffer(
+            storage_.data() + previous_size,
+            storage_.size() - previous_size),
+          ec));
+    resize_guard.commit();
+    return storage_.size() - previous_size;
+  }
+
+  template <typename ReadHandler>
+  class fill_handler
+  {
+  public:
+    fill_handler(asio::io_service& io_service,
+        detail::buffered_stream_storage& storage,
+        std::size_t previous_size, ReadHandler handler)
+      : io_service_(io_service),
+        storage_(storage),
+        previous_size_(previous_size),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_transferred)
+    {
+      storage_.resize(previous_size_ + bytes_transferred);
+      io_service_.dispatch(detail::bind_handler(
+            handler_, ec, bytes_transferred));
+    }
+
+  private:
+    asio::io_service& io_service_;
+    detail::buffered_stream_storage& storage_;
+    std::size_t previous_size_;
+    ReadHandler handler_;
+  };
+
+  /// Start an asynchronous fill.
+  template <typename ReadHandler>
+  void async_fill(ReadHandler handler)
+  {
+    std::size_t previous_size = storage_.size();
+    storage_.resize(storage_.capacity());
+    next_layer_.async_read_some(
+        buffer(
+          storage_.data() + previous_size,
+          storage_.size() - previous_size),
+        fill_handler<ReadHandler>(get_io_service(),
+          storage_, previous_size, handler));
+  }
+
+  /// Read some data from the stream. Returns the number of bytes read. Throws
+  /// an exception on failure.
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers)
+  {
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    size_t total_buffer_size = 0;
+    for (; iter != end; ++iter)
+    {
+      asio::mutable_buffer buffer(*iter);
+      total_buffer_size += asio::buffer_size(buffer);
+    }
+
+    if (total_buffer_size == 0)
+      return 0;
+
+    if (storage_.empty())
+      fill();
+
+    return copy(buffers);
+  }
+
+  /// Read some data from the stream. Returns the number of bytes read or 0 if
+  /// an error occurred.
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    ec = asio::error_code();
+
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    size_t total_buffer_size = 0;
+    for (; iter != end; ++iter)
+    {
+      asio::mutable_buffer buffer(*iter);
+      total_buffer_size += asio::buffer_size(buffer);
+    }
+
+    if (total_buffer_size == 0)
+      return 0;
+
+    if (storage_.empty() && !fill(ec))
+      return 0;
+
+    return copy(buffers);
+  }
+
+  template <typename MutableBufferSequence, typename ReadHandler>
+  class read_some_handler
+  {
+  public:
+    read_some_handler(asio::io_service& io_service,
+        detail::buffered_stream_storage& storage,
+        const MutableBufferSequence& buffers, ReadHandler handler)
+      : io_service_(io_service),
+        storage_(storage),
+        buffers_(buffers),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec, std::size_t)
+    {
+      if (ec || storage_.empty())
+      {
+        std::size_t length = 0;
+        io_service_.dispatch(detail::bind_handler(handler_, ec, length));
+      }
+      else
+      {
+        using namespace std; // For memcpy.
+
+        std::size_t bytes_avail = storage_.size();
+        std::size_t bytes_copied = 0;
+
+        typename MutableBufferSequence::const_iterator iter = buffers_.begin();
+        typename MutableBufferSequence::const_iterator end = buffers_.end();
+        for (; iter != end && bytes_avail > 0; ++iter)
+        {
+          std::size_t max_length = buffer_size(*iter);
+          std::size_t length = (max_length < bytes_avail)
+            ? max_length : bytes_avail;
+          memcpy(buffer_cast<void*>(*iter),
+              storage_.data() + bytes_copied, length);
+          bytes_copied += length;
+          bytes_avail -= length;
+        }
+
+        storage_.consume(bytes_copied);
+        io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
+      }
+    }
+
+  private:
+    asio::io_service& io_service_;
+    detail::buffered_stream_storage& storage_;
+    MutableBufferSequence buffers_;
+    ReadHandler handler_;
+  };
+
+  /// Start an asynchronous read. The buffer into which the data will be read
+  /// must be valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_read_some(const MutableBufferSequence& buffers,
+      ReadHandler handler)
+  {
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    size_t total_buffer_size = 0;
+    for (; iter != end; ++iter)
+    {
+      asio::mutable_buffer buffer(*iter);
+      total_buffer_size += asio::buffer_size(buffer);
+    }
+
+    if (total_buffer_size == 0)
+    {
+      get_io_service().post(detail::bind_handler(
+            handler, asio::error_code(), 0));
+    }
+    else if (storage_.empty())
+    {
+      async_fill(read_some_handler<MutableBufferSequence, ReadHandler>(
+            get_io_service(), storage_, buffers, handler));
+    }
+    else
+    {
+      std::size_t length = copy(buffers);
+      get_io_service().post(detail::bind_handler(
+            handler, asio::error_code(), length));
+    }
+  }
+
+  /// Peek at the incoming data on the stream. Returns the number of bytes read.
+  /// Throws an exception on failure.
+  template <typename MutableBufferSequence>
+  std::size_t peek(const MutableBufferSequence& buffers)
+  {
+    if (storage_.empty())
+      fill();
+    return peek_copy(buffers);
+  }
+
+  /// Peek at the incoming data on the stream. Returns the number of bytes read,
+  /// or 0 if an error occurred.
+  template <typename MutableBufferSequence>
+  std::size_t peek(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    ec = asio::error_code();
+    if (storage_.empty() && !fill(ec))
+      return 0;
+    return peek_copy(buffers);
+  }
+
+  /// Determine the amount of data that may be read without blocking.
+  std::size_t in_avail()
+  {
+    return storage_.size();
+  }
+
+  /// Determine the amount of data that may be read without blocking.
+  std::size_t in_avail(asio::error_code& ec)
+  {
+    ec = asio::error_code();
+    return storage_.size();
+  }
+
+private:
+  /// Copy data out of the internal buffer to the specified target buffer.
+  /// Returns the number of bytes copied.
+  template <typename MutableBufferSequence>
+  std::size_t copy(const MutableBufferSequence& buffers)
+  {
+    using namespace std; // For memcpy.
+
+    std::size_t bytes_avail = storage_.size();
+    std::size_t bytes_copied = 0;
+
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    for (; iter != end && bytes_avail > 0; ++iter)
+    {
+      std::size_t max_length = buffer_size(*iter);
+      std::size_t length = (max_length < bytes_avail)
+        ? max_length : bytes_avail;
+      memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
+      bytes_copied += length;
+      bytes_avail -= length;
+    }
+
+    storage_.consume(bytes_copied);
+    return bytes_copied;
+  }
+
+  /// Copy data from the internal buffer to the specified target buffer, without
+  /// removing the data from the internal buffer. Returns the number of bytes
+  /// copied.
+  template <typename MutableBufferSequence>
+  std::size_t peek_copy(const MutableBufferSequence& buffers)
+  {
+    using namespace std; // For memcpy.
+
+    std::size_t bytes_avail = storage_.size();
+    std::size_t bytes_copied = 0;
+
+    typename MutableBufferSequence::const_iterator iter = buffers.begin();
+    typename MutableBufferSequence::const_iterator end = buffers.end();
+    for (; iter != end && bytes_avail > 0; ++iter)
+    {
+      std::size_t max_length = buffer_size(*iter);
+      std::size_t length = (max_length < bytes_avail)
+        ? max_length : bytes_avail;
+      memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
+      bytes_copied += length;
+      bytes_avail -= length;
+    }
+
+    return bytes_copied;
+  }
+
+  /// The next layer.
+  Stream next_layer_;
+
+  // The data in the buffer.
+  detail::buffered_stream_storage storage_;
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BUFFERED_READ_STREAM_HPP

+ 29 - 0
ext/asio/asio/buffered_read_stream_fwd.hpp

@@ -0,0 +1,29 @@
+//
+// buffered_read_stream_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERED_READ_STREAM_FWD_HPP
+#define ASIO_BUFFERED_READ_STREAM_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Stream>
+class buffered_read_stream;
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP

+ 256 - 0
ext/asio/asio/buffered_stream.hpp

@@ -0,0 +1,256 @@
+//
+// buffered_stream.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERED_STREAM_HPP
+#define ASIO_BUFFERED_STREAM_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/buffered_read_stream.hpp"
+#include "asio/buffered_write_stream.hpp"
+#include "asio/buffered_stream_fwd.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+
+/// Adds buffering to the read- and write-related operations of a stream.
+/**
+ * The buffered_stream class template can be used to add buffering to the
+ * synchronous and asynchronous read and write operations of a stream.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Stream>
+class buffered_stream
+  : private noncopyable
+{
+public:
+  /// The type of the next layer.
+  typedef typename boost::remove_reference<Stream>::type next_layer_type;
+
+  /// The type of the lowest layer.
+  typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+
+  /// Construct, passing the specified argument to initialise the next layer.
+  template <typename Arg>
+  explicit buffered_stream(Arg& a)
+    : inner_stream_impl_(a),
+      stream_impl_(inner_stream_impl_)
+  {
+  }
+
+  /// Construct, passing the specified argument to initialise the next layer.
+  template <typename Arg>
+  explicit buffered_stream(Arg& a, std::size_t read_buffer_size,
+      std::size_t write_buffer_size)
+    : inner_stream_impl_(a, write_buffer_size),
+      stream_impl_(inner_stream_impl_, read_buffer_size)
+  {
+  }
+
+  /// Get a reference to the next layer.
+  next_layer_type& next_layer()
+  {
+    return stream_impl_.next_layer().next_layer();
+  }
+
+  /// Get a reference to the lowest layer.
+  lowest_layer_type& lowest_layer()
+  {
+    return stream_impl_.lowest_layer();
+  }
+
+  /// Get a const reference to the lowest layer.
+  const lowest_layer_type& lowest_layer() const
+  {
+    return stream_impl_.lowest_layer();
+  }
+
+  /// (Deprecated: use get_io_service().) Get the io_service associated with
+  /// the object.
+  asio::io_service& io_service()
+  {
+    return stream_impl_.get_io_service();
+  }
+
+  /// Get the io_service associated with the object.
+  asio::io_service& get_io_service()
+  {
+    return stream_impl_.get_io_service();
+  }
+
+  /// Close the stream.
+  void close()
+  {
+    stream_impl_.close();
+  }
+
+  /// Close the stream.
+  asio::error_code close(asio::error_code& ec)
+  {
+    return stream_impl_.close(ec);
+  }
+
+  /// Flush all data from the buffer to the next layer. Returns the number of
+  /// bytes written to the next layer on the last write operation. Throws an
+  /// exception on failure.
+  std::size_t flush()
+  {
+    return stream_impl_.next_layer().flush();
+  }
+
+  /// Flush all data from the buffer to the next layer. Returns the number of
+  /// bytes written to the next layer on the last write operation, or 0 if an
+  /// error occurred.
+  std::size_t flush(asio::error_code& ec)
+  {
+    return stream_impl_.next_layer().flush(ec);
+  }
+
+  /// Start an asynchronous flush.
+  template <typename WriteHandler>
+  void async_flush(WriteHandler handler)
+  {
+    return stream_impl_.next_layer().async_flush(handler);
+  }
+
+  /// Write the given data to the stream. Returns the number of bytes written.
+  /// Throws an exception on failure.
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers)
+  {
+    return stream_impl_.write_some(buffers);
+  }
+
+  /// Write the given data to the stream. Returns the number of bytes written,
+  /// or 0 if an error occurred.
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return stream_impl_.write_some(buffers, ec);
+  }
+
+  /// Start an asynchronous write. The data being written must be valid for the
+  /// lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_write_some(const ConstBufferSequence& buffers,
+      WriteHandler handler)
+  {
+    stream_impl_.async_write_some(buffers, handler);
+  }
+
+  /// Fill the buffer with some data. Returns the number of bytes placed in the
+  /// buffer as a result of the operation. Throws an exception on failure.
+  std::size_t fill()
+  {
+    return stream_impl_.fill();
+  }
+
+  /// Fill the buffer with some data. Returns the number of bytes placed in the
+  /// buffer as a result of the operation, or 0 if an error occurred.
+  std::size_t fill(asio::error_code& ec)
+  {
+    return stream_impl_.fill(ec);
+  }
+
+  /// Start an asynchronous fill.
+  template <typename ReadHandler>
+  void async_fill(ReadHandler handler)
+  {
+    stream_impl_.async_fill(handler);
+  }
+
+  /// Read some data from the stream. Returns the number of bytes read. Throws
+  /// an exception on failure.
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers)
+  {
+    return stream_impl_.read_some(buffers);
+  }
+
+  /// Read some data from the stream. Returns the number of bytes read or 0 if
+  /// an error occurred.
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return stream_impl_.read_some(buffers, ec);
+  }
+
+  /// Start an asynchronous read. The buffer into which the data will be read
+  /// must be valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_read_some(const MutableBufferSequence& buffers,
+      ReadHandler handler)
+  {
+    stream_impl_.async_read_some(buffers, handler);
+  }
+
+  /// Peek at the incoming data on the stream. Returns the number of bytes read.
+  /// Throws an exception on failure.
+  template <typename MutableBufferSequence>
+  std::size_t peek(const MutableBufferSequence& buffers)
+  {
+    return stream_impl_.peek(buffers);
+  }
+
+  /// Peek at the incoming data on the stream. Returns the number of bytes read,
+  /// or 0 if an error occurred.
+  template <typename MutableBufferSequence>
+  std::size_t peek(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return stream_impl_.peek(buffers, ec);
+  }
+
+  /// Determine the amount of data that may be read without blocking.
+  std::size_t in_avail()
+  {
+    return stream_impl_.in_avail();
+  }
+
+  /// Determine the amount of data that may be read without blocking.
+  std::size_t in_avail(asio::error_code& ec)
+  {
+    return stream_impl_.in_avail(ec);
+  }
+
+private:
+  // The buffered write stream.
+  typedef buffered_write_stream<Stream> write_stream_type;
+  write_stream_type inner_stream_impl_;
+
+  // The buffered read stream.
+  typedef buffered_read_stream<write_stream_type&> read_stream_type;
+  read_stream_type stream_impl_;
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BUFFERED_STREAM_HPP

+ 29 - 0
ext/asio/asio/buffered_stream_fwd.hpp

@@ -0,0 +1,29 @@
+//
+// buffered_stream_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERED_STREAM_FWD_HPP
+#define ASIO_BUFFERED_STREAM_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Stream>
+class buffered_stream;
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BUFFERED_STREAM_FWD_HPP

+ 415 - 0
ext/asio/asio/buffered_write_stream.hpp

@@ -0,0 +1,415 @@
+//
+// buffered_write_stream.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERED_WRITE_STREAM_HPP
+#define ASIO_BUFFERED_WRITE_STREAM_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 <cstddef>
+#include <cstring>
+#include <boost/config.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/buffered_write_stream_fwd.hpp"
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/write.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffered_stream_storage.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+
+/// Adds buffering to the write-related operations of a stream.
+/**
+ * The buffered_write_stream class template can be used to add buffering to the
+ * synchronous and asynchronous write operations of a stream.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Stream>
+class buffered_write_stream
+  : private noncopyable
+{
+public:
+  /// The type of the next layer.
+  typedef typename boost::remove_reference<Stream>::type next_layer_type;
+
+  /// The type of the lowest layer.
+  typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+
+#if defined(GENERATING_DOCUMENTATION)
+  /// The default buffer size.
+  static const std::size_t default_buffer_size = implementation_defined;
+#else
+  BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
+#endif
+
+  /// Construct, passing the specified argument to initialise the next layer.
+  template <typename Arg>
+  explicit buffered_write_stream(Arg& a)
+    : next_layer_(a),
+      storage_(default_buffer_size)
+  {
+  }
+
+  /// Construct, passing the specified argument to initialise the next layer.
+  template <typename Arg>
+  buffered_write_stream(Arg& a, std::size_t buffer_size)
+    : next_layer_(a),
+      storage_(buffer_size)
+  {
+  }
+
+  /// Get a reference to the next layer.
+  next_layer_type& next_layer()
+  {
+    return next_layer_;
+  }
+
+  /// Get a reference to the lowest layer.
+  lowest_layer_type& lowest_layer()
+  {
+    return next_layer_.lowest_layer();
+  }
+
+  /// Get a const reference to the lowest layer.
+  const lowest_layer_type& lowest_layer() const
+  {
+    return next_layer_.lowest_layer();
+  }
+
+  /// (Deprecated: use get_io_service().) Get the io_service associated with
+  /// the object.
+  asio::io_service& io_service()
+  {
+    return next_layer_.get_io_service();
+  }
+
+  /// Get the io_service associated with the object.
+  asio::io_service& get_io_service()
+  {
+    return next_layer_.get_io_service();
+  }
+
+  /// Close the stream.
+  void close()
+  {
+    next_layer_.close();
+  }
+
+  /// Close the stream.
+  asio::error_code close(asio::error_code& ec)
+  {
+    return next_layer_.close(ec);
+  }
+
+  /// Flush all data from the buffer to the next layer. Returns the number of
+  /// bytes written to the next layer on the last write operation. Throws an
+  /// exception on failure.
+  std::size_t flush()
+  {
+    std::size_t bytes_written = write(next_layer_,
+        buffer(storage_.data(), storage_.size()));
+    storage_.consume(bytes_written);
+    return bytes_written;
+  }
+
+  /// Flush all data from the buffer to the next layer. Returns the number of
+  /// bytes written to the next layer on the last write operation, or 0 if an
+  /// error occurred.
+  std::size_t flush(asio::error_code& ec)
+  {
+    std::size_t bytes_written = write(next_layer_,
+        buffer(storage_.data(), storage_.size()),
+        transfer_all(), ec);
+    storage_.consume(bytes_written);
+    return bytes_written;
+  }
+
+  template <typename WriteHandler>
+  class flush_handler
+  {
+  public:
+    flush_handler(asio::io_service& io_service,
+        detail::buffered_stream_storage& storage, WriteHandler handler)
+      : io_service_(io_service),
+        storage_(storage),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec,
+        std::size_t bytes_written)
+    {
+      storage_.consume(bytes_written);
+      io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written));
+    }
+
+  private:
+    asio::io_service& io_service_;
+    detail::buffered_stream_storage& storage_;
+    WriteHandler handler_;
+  };
+
+  /// Start an asynchronous flush.
+  template <typename WriteHandler>
+  void async_flush(WriteHandler handler)
+  {
+    async_write(next_layer_, buffer(storage_.data(), storage_.size()),
+        flush_handler<WriteHandler>(get_io_service(), storage_, handler));
+  }
+
+  /// Write the given data to the stream. Returns the number of bytes written.
+  /// Throws an exception on failure.
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers)
+  {
+    typename ConstBufferSequence::const_iterator iter = buffers.begin();
+    typename ConstBufferSequence::const_iterator end = buffers.end();
+    size_t total_buffer_size = 0;
+    for (; iter != end; ++iter)
+    {
+      asio::const_buffer buffer(*iter);
+      total_buffer_size += asio::buffer_size(buffer);
+    }
+
+    if (total_buffer_size == 0)
+      return 0;
+
+    if (storage_.size() == storage_.capacity())
+      flush();
+
+    return copy(buffers);
+  }
+
+  /// Write the given data to the stream. Returns the number of bytes written,
+  /// or 0 if an error occurred and the error handler did not throw.
+  template <typename ConstBufferSequence>
+  std::size_t write_some(const ConstBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    ec = asio::error_code();
+
+    typename ConstBufferSequence::const_iterator iter = buffers.begin();
+    typename ConstBufferSequence::const_iterator end = buffers.end();
+    size_t total_buffer_size = 0;
+    for (; iter != end; ++iter)
+    {
+      asio::const_buffer buffer(*iter);
+      total_buffer_size += asio::buffer_size(buffer);
+    }
+
+    if (total_buffer_size == 0)
+      return 0;
+
+    if (storage_.size() == storage_.capacity() && !flush(ec))
+      return 0;
+
+    return copy(buffers);
+  }
+
+  template <typename ConstBufferSequence, typename WriteHandler>
+  class write_some_handler
+  {
+  public:
+    write_some_handler(asio::io_service& io_service,
+        detail::buffered_stream_storage& storage,
+        const ConstBufferSequence& buffers, WriteHandler handler)
+      : io_service_(io_service),
+        storage_(storage),
+        buffers_(buffers),
+        handler_(handler)
+    {
+    }
+
+    void operator()(const asio::error_code& ec, std::size_t)
+    {
+      if (ec)
+      {
+        std::size_t length = 0;
+        io_service_.dispatch(detail::bind_handler(handler_, ec, length));
+      }
+      else
+      {
+        using namespace std; // For memcpy.
+
+        std::size_t orig_size = storage_.size();
+        std::size_t space_avail = storage_.capacity() - orig_size;
+        std::size_t bytes_copied = 0;
+
+        typename ConstBufferSequence::const_iterator iter = buffers_.begin();
+        typename ConstBufferSequence::const_iterator end = buffers_.end();
+        for (; iter != end && space_avail > 0; ++iter)
+        {
+          std::size_t bytes_avail = buffer_size(*iter);
+          std::size_t length = (bytes_avail < space_avail)
+            ? bytes_avail : space_avail;
+          storage_.resize(orig_size + bytes_copied + length);
+          memcpy(storage_.data() + orig_size + bytes_copied,
+              buffer_cast<const void*>(*iter), length);
+          bytes_copied += length;
+          space_avail -= length;
+        }
+
+        io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
+      }
+    }
+
+  private:
+    asio::io_service& io_service_;
+    detail::buffered_stream_storage& storage_;
+    ConstBufferSequence buffers_;
+    WriteHandler handler_;
+  };
+
+  /// Start an asynchronous write. The data being written must be valid for the
+  /// lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_write_some(const ConstBufferSequence& buffers,
+      WriteHandler handler)
+  {
+    typename ConstBufferSequence::const_iterator iter = buffers.begin();
+    typename ConstBufferSequence::const_iterator end = buffers.end();
+    size_t total_buffer_size = 0;
+    for (; iter != end; ++iter)
+    {
+      asio::const_buffer buffer(*iter);
+      total_buffer_size += asio::buffer_size(buffer);
+    }
+
+    if (total_buffer_size == 0)
+    {
+      get_io_service().post(detail::bind_handler(
+            handler, asio::error_code(), 0));
+    }
+    else if (storage_.size() == storage_.capacity())
+    {
+      async_flush(write_some_handler<ConstBufferSequence, WriteHandler>(
+            get_io_service(), storage_, buffers, handler));
+    }
+    else
+    {
+      std::size_t bytes_copied = copy(buffers);
+      get_io_service().post(detail::bind_handler(
+            handler, asio::error_code(), bytes_copied));
+    }
+  }
+
+  /// Read some data from the stream. Returns the number of bytes read. Throws
+  /// an exception on failure.
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers)
+  {
+    return next_layer_.read_some(buffers);
+  }
+
+  /// Read some data from the stream. Returns the number of bytes read or 0 if
+  /// an error occurred.
+  template <typename MutableBufferSequence>
+  std::size_t read_some(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return next_layer_.read_some(buffers, ec);
+  }
+
+  /// Start an asynchronous read. The buffer into which the data will be read
+  /// must be valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_read_some(const MutableBufferSequence& buffers,
+      ReadHandler handler)
+  {
+    next_layer_.async_read_some(buffers, handler);
+  }
+
+  /// Peek at the incoming data on the stream. Returns the number of bytes read.
+  /// Throws an exception on failure.
+  template <typename MutableBufferSequence>
+  std::size_t peek(const MutableBufferSequence& buffers)
+  {
+    return next_layer_.peek(buffers);
+  }
+
+  /// Peek at the incoming data on the stream. Returns the number of bytes read,
+  /// or 0 if an error occurred.
+  template <typename MutableBufferSequence>
+  std::size_t peek(const MutableBufferSequence& buffers,
+      asio::error_code& ec)
+  {
+    return next_layer_.peek(buffers, ec);
+  }
+
+  /// Determine the amount of data that may be read without blocking.
+  std::size_t in_avail()
+  {
+    return next_layer_.in_avail();
+  }
+
+  /// Determine the amount of data that may be read without blocking.
+  std::size_t in_avail(asio::error_code& ec)
+  {
+    return next_layer_.in_avail(ec);
+  }
+
+private:
+  /// Copy data into the internal buffer from the specified source buffer.
+  /// Returns the number of bytes copied.
+  template <typename ConstBufferSequence>
+  std::size_t copy(const ConstBufferSequence& buffers)
+  {
+    using namespace std; // For memcpy.
+
+    std::size_t orig_size = storage_.size();
+    std::size_t space_avail = storage_.capacity() - orig_size;
+    std::size_t bytes_copied = 0;
+
+    typename ConstBufferSequence::const_iterator iter = buffers.begin();
+    typename ConstBufferSequence::const_iterator end = buffers.end();
+    for (; iter != end && space_avail > 0; ++iter)
+    {
+      std::size_t bytes_avail = buffer_size(*iter);
+      std::size_t length = (bytes_avail < space_avail)
+        ? bytes_avail : space_avail;
+      storage_.resize(orig_size + bytes_copied + length);
+      memcpy(storage_.data() + orig_size + bytes_copied,
+          buffer_cast<const void*>(*iter), length);
+      bytes_copied += length;
+      space_avail -= length;
+    }
+
+    return bytes_copied;
+  }
+
+  /// The next layer.
+  Stream next_layer_;
+
+  // The data in the buffer.
+  detail::buffered_stream_storage storage_;
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BUFFERED_WRITE_STREAM_HPP

+ 29 - 0
ext/asio/asio/buffered_write_stream_fwd.hpp

@@ -0,0 +1,29 @@
+//
+// buffered_write_stream_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERED_WRITE_STREAM_FWD_HPP
+#define ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Stream>
+class buffered_write_stream;
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP

+ 447 - 0
ext/asio/asio/buffers_iterator.hpp

@@ -0,0 +1,447 @@
+//
+// buffers_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERS_ITERATOR_HPP
+#define ASIO_BUFFERS_ITERATOR_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 <cstddef>
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/iterator.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/buffer.hpp"
+
+namespace asio {
+
+namespace detail
+{
+  template <bool IsMutable>
+  struct buffers_iterator_types_helper;
+
+  template <>
+  struct buffers_iterator_types_helper<false>
+  {
+    typedef const_buffer buffer_type;
+    template <typename ByteType>
+    struct byte_type
+    {
+      typedef typename boost::add_const<ByteType>::type type;
+    };
+  };
+
+  template <>
+  struct buffers_iterator_types_helper<true>
+  {
+    typedef mutable_buffer buffer_type;
+    template <typename ByteType>
+    struct byte_type
+    {
+      typedef ByteType type;
+    };
+  };
+
+  template <typename BufferSequence, typename ByteType>
+  struct buffers_iterator_types
+  {
+    enum
+    {
+      is_mutable = boost::is_convertible<
+        typename BufferSequence::value_type, mutable_buffer>::value
+    };
+    typedef buffers_iterator_types_helper<is_mutable> helper;
+    typedef typename helper::buffer_type buffer_type;
+    typedef typename helper::template byte_type<ByteType>::type byte_type;
+  };
+}
+
+/// A random access iterator over the bytes in a buffer sequence.
+template <typename BufferSequence, typename ByteType = char>
+class buffers_iterator
+  : public boost::iterator<
+      std::random_access_iterator_tag,
+      typename detail::buffers_iterator_types<
+        BufferSequence, ByteType>::byte_type>
+{
+private:
+  typedef typename detail::buffers_iterator_types<
+      BufferSequence, ByteType>::buffer_type buffer_type;
+  typedef typename detail::buffers_iterator_types<
+      BufferSequence, ByteType>::byte_type byte_type;
+
+public:
+  /// Default constructor. Creates an iterator in an undefined state.
+  buffers_iterator()
+    : current_buffer_(),
+      current_buffer_position_(0),
+      begin_(),
+      current_(),
+      end_(),
+      position_(0)
+  {
+  }
+
+  /// Construct an iterator representing the beginning of the buffers' data.
+  static buffers_iterator begin(const BufferSequence& buffers)
+#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
+    __attribute__ ((noinline))
+#endif
+  {
+    buffers_iterator new_iter;
+    new_iter.begin_ = buffers.begin();
+    new_iter.current_ = buffers.begin();
+    new_iter.end_ = buffers.end();
+    while (new_iter.current_ != new_iter.end_)
+    {
+      new_iter.current_buffer_ = *new_iter.current_;
+      if (asio::buffer_size(new_iter.current_buffer_) > 0)
+        break;
+      ++new_iter.current_;
+    }
+    return new_iter;
+  }
+
+  /// Construct an iterator representing the end of the buffers' data.
+  static buffers_iterator end(const BufferSequence& buffers)
+#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
+    __attribute__ ((noinline))
+#endif
+  {
+    buffers_iterator new_iter;
+    new_iter.begin_ = buffers.begin();
+    new_iter.current_ = buffers.begin();
+    new_iter.end_ = buffers.end();
+    while (new_iter.current_ != new_iter.end_)
+    {
+      buffer_type buffer = *new_iter.current_;
+      new_iter.position_ += asio::buffer_size(buffer);
+      ++new_iter.current_;
+    }
+    return new_iter;
+  }
+
+  /// Dereference an iterator.
+  byte_type& operator*() const
+  {
+    return dereference();
+  }
+
+  /// Dereference an iterator.
+  byte_type* operator->() const
+  {
+    return &dereference();
+  }
+
+  /// Access an individual element.
+  byte_type& operator[](std::ptrdiff_t difference) const
+  {
+    buffers_iterator tmp(*this);
+    tmp.advance(difference);
+    return *tmp;
+  }
+
+  /// Increment operator (prefix).
+  buffers_iterator& operator++()
+  {
+    increment();
+    return *this;
+  }
+
+  /// Increment operator (postfix).
+  buffers_iterator operator++(int)
+  {
+    buffers_iterator tmp(*this);
+    ++*this;
+    return tmp;
+  }
+
+  /// Decrement operator (prefix).
+  buffers_iterator& operator--()
+  {
+    decrement();
+    return *this;
+  }
+
+  /// Decrement operator (postfix).
+  buffers_iterator operator--(int)
+  {
+    buffers_iterator tmp(*this);
+    --*this;
+    return tmp;
+  }
+
+  /// Addition operator.
+  buffers_iterator& operator+=(std::ptrdiff_t difference)
+  {
+    advance(difference);
+    return *this;
+  }
+
+  /// Subtraction operator.
+  buffers_iterator& operator-=(std::ptrdiff_t difference)
+  {
+    advance(-difference);
+    return *this;
+  }
+
+  /// Addition operator.
+  friend buffers_iterator operator+(const buffers_iterator& iter,
+      std::ptrdiff_t difference)
+  {
+    buffers_iterator tmp(iter);
+    tmp.advance(difference);
+    return tmp;
+  }
+
+  /// Subtraction operator.
+  friend buffers_iterator operator-(const buffers_iterator& iter,
+      std::ptrdiff_t difference)
+  {
+    buffers_iterator tmp(iter);
+    tmp.advance(-difference);
+    return tmp;
+  }
+
+  /// Subtraction operator.
+  friend std::ptrdiff_t operator-(const buffers_iterator& a,
+      const buffers_iterator& b)
+  {
+    return b.distance_to(a);
+  }
+
+  /// Test two iterators for equality.
+  friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
+  {
+    return a.equal(b);
+  }
+
+  /// Test two iterators for inequality.
+  friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
+  {
+    return !a.equal(b);
+  }
+
+  /// Compare two iterators.
+  friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
+  {
+    return a.distance_to(b) > 0;
+  }
+
+  /// Compare two iterators.
+  friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
+  {
+    return !(b < a);
+  }
+
+  /// Compare two iterators.
+  friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
+  {
+    return b < a;
+  }
+
+  /// Compare two iterators.
+  friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
+  {
+    return !(a < b);
+  }
+
+private:
+  // Dereference the iterator.
+  byte_type& dereference() const
+  {
+    return buffer_cast<byte_type*>(current_buffer_)[current_buffer_position_];
+  }
+
+  // Compare two iterators for equality.
+  bool equal(const buffers_iterator& other) const
+  {
+    return position_ == other.position_;
+  }
+
+  // Increment the iterator.
+  void increment()
+  {
+    BOOST_ASSERT(current_ != end_ && "iterator out of bounds");
+    ++position_;
+
+    // Check if the increment can be satisfied by the current buffer.
+    ++current_buffer_position_;
+    if (current_buffer_position_ != asio::buffer_size(current_buffer_))
+      return;
+
+    // Find the next non-empty buffer.
+    ++current_;
+    current_buffer_position_ = 0;
+    while (current_ != end_)
+    {
+      current_buffer_ = *current_;
+      if (asio::buffer_size(current_buffer_) > 0)
+        return;
+      ++current_;
+    }
+  }
+
+  // Decrement the iterator.
+  void decrement()
+  {
+    BOOST_ASSERT(position_ > 0 && "iterator out of bounds");
+    --position_;
+
+    // Check if the decrement can be satisfied by the current buffer.
+    if (current_buffer_position_ != 0)
+    {
+      --current_buffer_position_;
+      return;
+    }
+
+    // Find the previous non-empty buffer.
+    typename BufferSequence::const_iterator iter = current_;
+    while (iter != begin_)
+    {
+      --iter;
+      buffer_type buffer = *iter;
+      std::size_t buffer_size = asio::buffer_size(buffer);
+      if (buffer_size > 0)
+      {
+        current_ = iter;
+        current_buffer_ = buffer;
+        current_buffer_position_ = buffer_size - 1;
+        return;
+      }
+    }
+  }
+
+  // Advance the iterator by the specified distance.
+  void advance(std::ptrdiff_t n)
+  {
+    if (n > 0)
+    {
+      BOOST_ASSERT(current_ != end_ && "iterator out of bounds");
+      for (;;)
+      {
+        std::ptrdiff_t current_buffer_balance
+          = asio::buffer_size(current_buffer_)
+          - current_buffer_position_;
+
+        // Check if the advance can be satisfied by the current buffer.
+        if (current_buffer_balance > n)
+        {
+          position_ += n;
+          current_buffer_position_ += n;
+          return;
+        }
+
+        // Update position.
+        n -= current_buffer_balance;
+        position_ += current_buffer_balance;
+
+        // Move to next buffer. If it is empty then it will be skipped on the
+        // next iteration of this loop.
+        if (++current_ == end_)
+        {
+          BOOST_ASSERT(n == 0 && "iterator out of bounds");
+          current_buffer_ = buffer_type();
+          current_buffer_position_ = 0;
+          return;
+        }
+        current_buffer_ = *current_;
+        current_buffer_position_ = 0;
+      }
+    }
+    else if (n < 0)
+    {
+      std::size_t abs_n = -n;
+      BOOST_ASSERT(position_ >= abs_n && "iterator out of bounds");
+      for (;;)
+      {
+        // Check if the advance can be satisfied by the current buffer.
+        if (current_buffer_position_ >= abs_n)
+        {
+          position_ -= abs_n;
+          current_buffer_position_ -= abs_n;
+          return;
+        }
+
+        // Update position.
+        abs_n -= current_buffer_position_;
+        position_ -= current_buffer_position_;
+
+        // Check if we've reached the beginning of the buffers.
+        if (current_ == begin_)
+        {
+          BOOST_ASSERT(abs_n == 0 && "iterator out of bounds");
+          current_buffer_position_ = 0;
+          return;
+        }
+
+        // Find the previous non-empty buffer.
+        typename BufferSequence::const_iterator iter = current_;
+        while (iter != begin_)
+        {
+          --iter;
+          buffer_type buffer = *iter;
+          std::size_t buffer_size = asio::buffer_size(buffer);
+          if (buffer_size > 0)
+          {
+            current_ = iter;
+            current_buffer_ = buffer;
+            current_buffer_position_ = buffer_size;
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  // Determine the distance between two iterators.
+  std::ptrdiff_t distance_to(const buffers_iterator& other) const
+  {
+    return other.position_ - position_;
+  }
+
+  buffer_type current_buffer_;
+  std::size_t current_buffer_position_;
+  typename BufferSequence::const_iterator begin_;
+  typename BufferSequence::const_iterator current_;
+  typename BufferSequence::const_iterator end_;
+  std::size_t position_;
+};
+
+/// Construct an iterator representing the beginning of the buffers' data.
+template <typename BufferSequence>
+inline buffers_iterator<BufferSequence> buffers_begin(
+    const BufferSequence& buffers)
+{
+  return buffers_iterator<BufferSequence>::begin(buffers);
+}
+
+/// Construct an iterator representing the end of the buffers' data.
+template <typename BufferSequence>
+inline buffers_iterator<BufferSequence> buffers_end(
+    const BufferSequence& buffers)
+{
+  return buffers_iterator<BufferSequence>::end(buffers);
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_BUFFERS_ITERATOR_HPP

+ 164 - 0
ext/asio/asio/completion_condition.hpp

@@ -0,0 +1,164 @@
+//
+// completion_condition.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_COMPLETION_CONDITION_HPP
+#define ASIO_COMPLETION_CONDITION_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+namespace asio {
+
+namespace detail {
+
+// The default maximum number of bytes to transfer in a single operation.
+enum { default_max_transfer_size = 65536 };
+
+// Adapt result of old-style completion conditions (which had a bool result
+// where true indicated that the operation was complete).
+inline std::size_t adapt_completion_condition_result(bool result)
+{
+  return result ? 0 : default_max_transfer_size;
+}
+
+// Adapt result of current completion conditions (which have a size_t result
+// where 0 means the operation is complete, and otherwise the result is the
+// maximum number of bytes to transfer on the next underlying operation).
+inline std::size_t adapt_completion_condition_result(std::size_t result)
+{
+  return result;
+}
+
+class transfer_all_t
+{
+public:
+  typedef std::size_t result_type;
+
+  template <typename Error>
+  std::size_t operator()(const Error& err, std::size_t)
+  {
+    return !!err ? 0 : default_max_transfer_size;
+  }
+};
+
+class transfer_at_least_t
+{
+public:
+  typedef std::size_t result_type;
+
+  explicit transfer_at_least_t(std::size_t minimum)
+    : minimum_(minimum)
+  {
+  }
+
+  template <typename Error>
+  std::size_t operator()(const Error& err, std::size_t bytes_transferred)
+  {
+    return (!!err || bytes_transferred >= minimum_)
+      ? 0 : default_max_transfer_size;
+  }
+
+private:
+  std::size_t minimum_;
+};
+
+} // namespace detail
+
+/**
+ * @defgroup completion_condition Completion Condition Function Objects
+ *
+ * Function objects used for determining when a read or write operation should
+ * complete.
+ */
+/*@{*/
+
+/// Return a completion condition function object that indicates that a read or
+/// write operation should continue until all of the data has been transferred,
+/// or until an error occurs.
+/**
+ * This function is used to create an object, of unspecified type, that meets
+ * CompletionCondition requirements.
+ *
+ * @par Example
+ * Reading until a buffer is full:
+ * @code
+ * boost::array<char, 128> buf;
+ * asio::error_code ec;
+ * std::size_t n = asio::read(
+ *     sock, asio::buffer(buf),
+ *     asio::transfer_all(), ec);
+ * if (ec)
+ * {
+ *   // An error occurred.
+ * }
+ * else
+ * {
+ *   // n == 128
+ * }
+ * @endcode
+ */
+#if defined(GENERATING_DOCUMENTATION)
+unspecified transfer_all();
+#else
+inline detail::transfer_all_t transfer_all()
+{
+  return detail::transfer_all_t();
+}
+#endif
+
+/// Return a completion condition function object that indicates that a read or
+/// write operation should continue until a minimum number of bytes has been
+/// transferred, or until an error occurs.
+/**
+ * This function is used to create an object, of unspecified type, that meets
+ * CompletionCondition requirements.
+ *
+ * @par Example
+ * Reading until a buffer is full or contains at least 64 bytes:
+ * @code
+ * boost::array<char, 128> buf;
+ * asio::error_code ec;
+ * std::size_t n = asio::read(
+ *     sock, asio::buffer(buf),
+ *     asio::transfer_at_least(64), ec);
+ * if (ec)
+ * {
+ *   // An error occurred.
+ * }
+ * else
+ * {
+ *   // n >= 64 && n <= 128
+ * }
+ * @endcode
+ */
+#if defined(GENERATING_DOCUMENTATION)
+unspecified transfer_at_least(std::size_t minimum);
+#else
+inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum)
+{
+  return detail::transfer_at_least_t(minimum);
+}
+#endif
+
+/*@}*/
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_COMPLETION_CONDITION_HPP

+ 315 - 0
ext/asio/asio/datagram_socket_service.hpp

@@ -0,0 +1,315 @@
+//
+// datagram_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DATAGRAM_SOCKET_SERVICE_HPP
+#define ASIO_DATAGRAM_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/service_base.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_socket_service.hpp"
+#else
+# include "asio/detail/reactive_socket_service.hpp"
+#endif
+
+namespace asio {
+
+/// Default service implementation for a datagram socket.
+template <typename Protocol>
+class datagram_socket_service
+#if defined(GENERATING_DOCUMENTATION)
+  : public asio::io_service::service
+#else
+  : public asio::detail::service_base<datagram_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 datagram socket.
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined implementation_type;
+#else
+  typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+  /// The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined native_type;
+#else
+  typedef typename service_impl_type::native_type native_type;
+#endif
+
+  /// Construct a new datagram socket service for the specified io_service.
+  explicit datagram_socket_service(asio::io_service& io_service)
+    : asio::detail::service_base<
+        datagram_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 datagram socket implementation.
+  void construct(implementation_type& impl)
+  {
+    service_impl_.construct(impl);
+  }
+
+  /// Destroy a datagram socket implementation.
+  void destroy(implementation_type& impl)
+  {
+    service_impl_.destroy(impl);
+  }
+
+  // Open a new datagram socket implementation.
+  asio::error_code open(implementation_type& impl,
+      const protocol_type& protocol, asio::error_code& ec)
+  {
+    if (protocol.type() == SOCK_DGRAM)
+      service_impl_.open(impl, protocol, ec);
+    else
+      ec = asio::error::invalid_argument;
+    return ec;
+  }
+
+  /// Assign an existing native socket to a datagram socket.
+  asio::error_code assign(implementation_type& impl,
+      const protocol_type& protocol, const native_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 datagram socket implementation.
+  asio::error_code close(implementation_type& impl,
+      asio::error_code& ec)
+  {
+    return service_impl_.close(impl, ec);
+  }
+
+  /// Get the native socket implementation.
+  native_type native(implementation_type& impl)
+  {
+    return service_impl_.native(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 datagram 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 datagram 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);
+  }
+
+  /// 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);
+  }
+
+  /// Send a datagram to the specified endpoint.
+  template <typename ConstBufferSequence>
+  std::size_t send_to(implementation_type& impl,
+      const ConstBufferSequence& buffers, const endpoint_type& destination,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    return service_impl_.send_to(impl, buffers, destination, flags, ec);
+  }
+
+  /// Start an asynchronous send.
+  template <typename ConstBufferSequence, typename WriteHandler>
+  void async_send_to(implementation_type& impl,
+      const ConstBufferSequence& buffers, const endpoint_type& destination,
+      socket_base::message_flags flags, WriteHandler handler)
+  {
+    service_impl_.async_send_to(impl, buffers, destination, 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 flags, asio::error_code& ec)
+  {
+    return service_impl_.receive(impl, buffers, flags, ec);
+  }
+
+  /// Start an asynchronous receive.
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_receive(implementation_type& impl,
+      const MutableBufferSequence& buffers,
+      socket_base::message_flags flags, ReadHandler handler)
+  {
+    service_impl_.async_receive(impl, buffers, flags, handler);
+  }
+
+  /// Receive a datagram with the endpoint of the sender.
+  template <typename MutableBufferSequence>
+  std::size_t receive_from(implementation_type& impl,
+      const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+      socket_base::message_flags flags, asio::error_code& ec)
+  {
+    return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
+        ec);
+  }
+
+  /// Start an asynchronous receive that will get the endpoint of the sender.
+  template <typename MutableBufferSequence, typename ReadHandler>
+  void async_receive_from(implementation_type& impl,
+      const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+      socket_base::message_flags flags, ReadHandler handler)
+  {
+    service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags,
+        handler);
+  }
+
+private:
+  // The platform-specific implementation.
+  service_impl_type service_impl_;
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DATAGRAM_SOCKET_SERVICE_HPP

+ 37 - 0
ext/asio/asio/deadline_timer.hpp

@@ -0,0 +1,37 @@
+//
+// deadline_timer.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DEADLINE_TIMER_HPP
+#define ASIO_DEADLINE_TIMER_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/socket_types.hpp" // Must come before posix_time.
+
+#include "asio/detail/push_options.hpp"
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/basic_deadline_timer.hpp"
+
+namespace asio {
+
+/// Typedef for the typical usage of timer. Uses a UTC clock.
+typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DEADLINE_TIMER_HPP

+ 150 - 0
ext/asio/asio/deadline_timer_service.hpp

@@ -0,0 +1,150 @@
+//
+// deadline_timer_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DEADLINE_TIMER_SERVICE_HPP
+#define ASIO_DEADLINE_TIMER_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/io_service.hpp"
+#include "asio/time_traits.hpp"
+#include "asio/detail/deadline_timer_service.hpp"
+#include "asio/detail/service_base.hpp"
+
+namespace asio {
+
+/// Default service implementation for a timer.
+template <typename TimeType,
+    typename TimeTraits = asio::time_traits<TimeType> >
+class deadline_timer_service
+#if defined(GENERATING_DOCUMENTATION)
+  : public asio::io_service::service
+#else
+  : public asio::detail::service_base<
+      deadline_timer_service<TimeType, TimeTraits> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+  /// The unique service identifier.
+  static asio::io_service::id id;
+#endif
+
+  /// The time traits type.
+  typedef TimeTraits traits_type;
+
+  /// The time type.
+  typedef typename traits_type::time_type time_type;
+
+  /// The duration type.
+  typedef typename traits_type::duration_type duration_type;
+
+private:
+  // The type of the platform-specific implementation.
+  typedef detail::deadline_timer_service<traits_type> service_impl_type;
+
+public:
+  /// The implementation type of the deadline timer.
+#if defined(GENERATING_DOCUMENTATION)
+  typedef implementation_defined implementation_type;
+#else
+  typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+  /// Construct a new timer service for the specified io_service.
+  explicit deadline_timer_service(asio::io_service& io_service)
+    : asio::detail::service_base<
+        deadline_timer_service<TimeType, TimeTraits> >(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 timer implementation.
+  void construct(implementation_type& impl)
+  {
+    service_impl_.construct(impl);
+  }
+
+  /// Destroy a timer implementation.
+  void destroy(implementation_type& impl)
+  {
+    service_impl_.destroy(impl);
+  }
+
+  /// Cancel any asynchronous wait operations associated with the timer.
+  std::size_t cancel(implementation_type& impl, asio::error_code& ec)
+  {
+    return service_impl_.cancel(impl, ec);
+  }
+
+  /// Get the expiry time for the timer as an absolute time.
+  time_type expires_at(const implementation_type& impl) const
+  {
+    return service_impl_.expires_at(impl);
+  }
+
+  /// Set the expiry time for the timer as an absolute time.
+  std::size_t expires_at(implementation_type& impl,
+      const time_type& expiry_time, asio::error_code& ec)
+  {
+    return service_impl_.expires_at(impl, expiry_time, ec);
+  }
+
+  /// Get the expiry time for the timer relative to now.
+  duration_type expires_from_now(const implementation_type& impl) const
+  {
+    return service_impl_.expires_from_now(impl);
+  }
+
+  /// Set the expiry time for the timer relative to now.
+  std::size_t expires_from_now(implementation_type& impl,
+      const duration_type& expiry_time, asio::error_code& ec)
+  {
+    return service_impl_.expires_from_now(impl, expiry_time, ec);
+  }
+
+  // Perform a blocking wait on the timer.
+  void wait(implementation_type& impl, asio::error_code& ec)
+  {
+    service_impl_.wait(impl, ec);
+  }
+
+  // Start an asynchronous wait on the timer.
+  template <typename WaitHandler>
+  void async_wait(implementation_type& impl, WaitHandler handler)
+  {
+    service_impl_.async_wait(impl, handler);
+  }
+
+private:
+  // The platform-specific implementation.
+  service_impl_type service_impl_;
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DEADLINE_TIMER_SERVICE_HPP

+ 65 - 0
ext/asio/asio/detail/base_from_completion_cond.hpp

@@ -0,0 +1,65 @@
+//
+// base_from_completion_cond.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BASE_FROM_COMPLETION_COND_HPP
+#define ASIO_DETAIL_BASE_FROM_COMPLETION_COND_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/completion_condition.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename CompletionCondition>
+class base_from_completion_cond
+{
+protected:
+  explicit base_from_completion_cond(CompletionCondition completion_condition)
+    : completion_condition_(completion_condition)
+  {
+  }
+
+  std::size_t check(const asio::error_code& ec,
+      std::size_t total_transferred)
+  {
+    return detail::adapt_completion_condition_result(
+        completion_condition_(ec, total_transferred));
+  }
+
+private:
+  CompletionCondition completion_condition_;
+};
+
+template <>
+class base_from_completion_cond<transfer_all_t>
+{
+protected:
+  explicit base_from_completion_cond(transfer_all_t)
+  {
+  }
+
+  static std::size_t check(const asio::error_code& ec,
+      std::size_t total_transferred)
+  {
+    return transfer_all_t()(ec, total_transferred);
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP

+ 349 - 0
ext/asio/asio/detail/bind_handler.hpp

@@ -0,0 +1,349 @@
+//
+// bind_handler.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BIND_HANDLER_HPP
+#define ASIO_DETAIL_BIND_HANDLER_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/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler, typename Arg1>
+class binder1
+{
+public:
+  binder1(const Handler& handler, const Arg1& arg1)
+    : handler_(handler),
+      arg1_(arg1)
+  {
+  }
+
+  void operator()()
+  {
+    handler_(arg1_);
+  }
+
+  void operator()() const
+  {
+    handler_(arg1_);
+  }
+
+//private:
+  Handler handler_;
+  Arg1 arg1_;
+};
+
+template <typename Handler, typename Arg1>
+inline void* asio_handler_allocate(std::size_t size,
+    binder1<Handler, Arg1>* this_handler)
+{
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+    binder1<Handler, Arg1>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1>
+inline void asio_handler_invoke(const Function& function,
+    binder1<Handler, Arg1>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      function, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline binder1<Handler, Arg1> bind_handler(const Handler& handler,
+    const Arg1& arg1)
+{
+  return binder1<Handler, Arg1>(handler, arg1);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+class binder2
+{
+public:
+  binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2)
+    : handler_(handler),
+      arg1_(arg1),
+      arg2_(arg2)
+  {
+  }
+
+  void operator()()
+  {
+    handler_(arg1_, arg2_);
+  }
+
+  void operator()() const
+  {
+    handler_(arg1_, arg2_);
+  }
+
+//private:
+  Handler handler_;
+  Arg1 arg1_;
+  Arg2 arg2_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void* asio_handler_allocate(std::size_t size,
+    binder2<Handler, Arg1, Arg2>* this_handler)
+{
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+    binder2<Handler, Arg1, Arg2>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_invoke(const Function& function,
+    binder2<Handler, Arg1, Arg2>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      function, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline binder2<Handler, Arg1, Arg2> bind_handler(const Handler& handler,
+    const Arg1& arg1, const Arg2& arg2)
+{
+  return binder2<Handler, Arg1, Arg2>(handler, arg1, arg2);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+class binder3
+{
+public:
+  binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+      const Arg3& arg3)
+    : handler_(handler),
+      arg1_(arg1),
+      arg2_(arg2),
+      arg3_(arg3)
+  {
+  }
+
+  void operator()()
+  {
+    handler_(arg1_, arg2_, arg3_);
+  }
+
+  void operator()() const
+  {
+    handler_(arg1_, arg2_, arg3_);
+  }
+
+//private:
+  Handler handler_;
+  Arg1 arg1_;
+  Arg2 arg2_;
+  Arg3 arg3_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+inline void* asio_handler_allocate(std::size_t size,
+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
+{
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2,
+    typename Arg3>
+inline void asio_handler_invoke(const Function& function,
+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      function, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+inline binder3<Handler, Arg1, Arg2, Arg3> bind_handler(const Handler& handler,
+    const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
+{
+  return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4>
+class binder4
+{
+public:
+  binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+      const Arg3& arg3, const Arg4& arg4)
+    : handler_(handler),
+      arg1_(arg1),
+      arg2_(arg2),
+      arg3_(arg3),
+      arg4_(arg4)
+  {
+  }
+
+  void operator()()
+  {
+    handler_(arg1_, arg2_, arg3_, arg4_);
+  }
+
+  void operator()() const
+  {
+    handler_(arg1_, arg2_, arg3_, arg4_);
+  }
+
+//private:
+  Handler handler_;
+  Arg1 arg1_;
+  Arg2 arg2_;
+  Arg3 arg3_;
+  Arg4 arg4_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4>
+inline void* asio_handler_allocate(std::size_t size,
+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
+{
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2,
+    typename Arg3, typename Arg4>
+inline void asio_handler_invoke(const Function& function,
+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      function, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4>
+inline binder4<Handler, Arg1, Arg2, Arg3, Arg4> bind_handler(
+    const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+    const Arg3& arg3, const Arg4& arg4)
+{
+  return binder4<Handler, Arg1, Arg2, Arg3, Arg4>(handler, arg1, arg2, arg3,
+      arg4);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4, typename Arg5>
+class binder5
+{
+public:
+  binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+      const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
+    : handler_(handler),
+      arg1_(arg1),
+      arg2_(arg2),
+      arg3_(arg3),
+      arg4_(arg4),
+      arg5_(arg5)
+  {
+  }
+
+  void operator()()
+  {
+    handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
+  }
+
+  void operator()() const
+  {
+    handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
+  }
+
+//private:
+  Handler handler_;
+  Arg1 arg1_;
+  Arg2 arg2_;
+  Arg3 arg3_;
+  Arg4 arg4_;
+  Arg5 arg5_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4, typename Arg5>
+inline void* asio_handler_allocate(std::size_t size,
+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
+{
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4, typename Arg5>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2,
+    typename Arg3, typename Arg4, typename Arg5>
+inline void asio_handler_invoke(const Function& function,
+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      function, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+    typename Arg4, typename Arg5>
+inline binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5> bind_handler(
+    const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+    const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
+{
+  return binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>(handler, arg1, arg2,
+      arg3, arg4, arg5);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_BIND_HANDLER_HPP

+ 70 - 0
ext/asio/asio/detail/buffer_resize_guard.hpp

@@ -0,0 +1,70 @@
+//
+// buffer_resize_guard.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFER_RESIZE_GUARD_HPP
+#define ASIO_DETAIL_BUFFER_RESIZE_GUARD_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/config.hpp>
+#include <boost/limits.hpp>
+#include "asio/detail/pop_options.hpp"
+
+namespace asio {
+namespace detail {
+
+// Helper class to manage buffer resizing in an exception safe way.
+template <typename Buffer>
+class buffer_resize_guard
+{
+public:
+  // Constructor.
+  buffer_resize_guard(Buffer& buffer)
+    : buffer_(buffer),
+      old_size_(buffer.size())
+  {
+  }
+
+  // Destructor rolls back the buffer resize unless commit was called.
+  ~buffer_resize_guard()
+  {
+    if (old_size_
+        != std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION())
+    {
+      buffer_.resize(old_size_);
+    }
+  }
+
+  // Commit the resize transaction.
+  void commit()
+  {
+    old_size_
+      = std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION();
+  }
+
+private:
+  // The buffer being managed.
+  Buffer& buffer_;
+
+  // The size of the buffer at the time the guard was constructed.
+  size_t old_size_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP

+ 252 - 0
ext/asio/asio/detail/buffer_sequence_adapter.hpp

@@ -0,0 +1,252 @@
+//
+// buffer_sequence_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFER_SEQUENCE_ADAPTER_HPP
+#define ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_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/buffer.hpp"
+
+namespace asio {
+namespace detail {
+
+class buffer_sequence_adapter_base
+{
+protected:
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  typedef WSABUF native_buffer_type;
+
+  static void init_native_buffer(WSABUF& buf,
+      const asio::mutable_buffer& buffer)
+  {
+    buf.buf = asio::buffer_cast<char*>(buffer);
+    buf.len = asio::buffer_size(buffer);
+  }
+
+  static void init_native_buffer(WSABUF& buf,
+      const asio::const_buffer& buffer)
+  {
+    buf.buf = const_cast<char*>(asio::buffer_cast<const char*>(buffer));
+    buf.len = asio::buffer_size(buffer);
+  }
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  typedef iovec native_buffer_type;
+
+  static void init_iov_base(void*& base, void* addr)
+  {
+    base = addr;
+  }
+
+  template <typename T>
+  static void init_iov_base(T& base, void* addr)
+  {
+    base = static_cast<T>(addr);
+  }
+
+  static void init_native_buffer(iovec& iov,
+      const asio::mutable_buffer& buffer)
+  {
+    init_iov_base(iov.iov_base, asio::buffer_cast<void*>(buffer));
+    iov.iov_len = asio::buffer_size(buffer);
+  }
+
+  static void init_native_buffer(iovec& iov,
+      const asio::const_buffer& buffer)
+  {
+    init_iov_base(iov.iov_base, const_cast<void*>(
+          asio::buffer_cast<const void*>(buffer)));
+    iov.iov_len = asio::buffer_size(buffer);
+  }
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+};
+
+// Helper class to translate buffers into the native buffer representation.
+template <typename Buffer, typename Buffers>
+class buffer_sequence_adapter
+  : buffer_sequence_adapter_base
+{
+public:
+  explicit buffer_sequence_adapter(const Buffers& buffers)
+    : count_(0), total_buffer_size_(0)
+  {
+    typename Buffers::const_iterator iter = buffers.begin();
+    typename Buffers::const_iterator end = buffers.end();
+    for (; iter != end && count_ < max_buffers; ++iter, ++count_)
+    {
+      Buffer buffer(*iter);
+      init_native_buffer(buffers_[count_], buffer);
+      total_buffer_size_ += asio::buffer_size(buffer);
+    }
+  }
+
+  native_buffer_type* buffers()
+  {
+    return buffers_;
+  }
+
+  std::size_t count() const
+  {
+    return count_;
+  }
+
+  bool all_empty() const
+  {
+    return total_buffer_size_ == 0;
+  }
+
+  static bool all_empty(const Buffers& buffers)
+  {
+    typename Buffers::const_iterator iter = buffers.begin();
+    typename Buffers::const_iterator end = buffers.end();
+    std::size_t i = 0;
+    for (; iter != end && i < max_buffers; ++iter, ++i)
+      if (asio::buffer_size(Buffer(*iter)) > 0)
+        return false;
+    return true;
+  }
+
+  static void validate(const Buffers& buffers)
+  {
+    typename Buffers::const_iterator iter = buffers.begin();
+    typename Buffers::const_iterator end = buffers.end();
+    for (; iter != end; ++iter)
+    {
+      Buffer buffer(*iter);
+      asio::buffer_cast<const void*>(buffer);
+    }
+  }
+
+  static Buffer first(const Buffers& buffers)
+  {
+    typename Buffers::const_iterator iter = buffers.begin();
+    typename Buffers::const_iterator end = buffers.end();
+    for (; iter != end; ++iter)
+    {
+      Buffer buffer(*iter);
+      if (asio::buffer_size(buffer) != 0)
+        return buffer;
+    }
+    return Buffer();
+  }
+
+private:
+  // The maximum number of buffers to support in a single operation.
+  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+
+  native_buffer_type buffers_[max_buffers];
+  std::size_t count_;
+  std::size_t total_buffer_size_;
+};
+
+template <typename Buffer>
+class buffer_sequence_adapter<Buffer, asio::mutable_buffers_1>
+  : buffer_sequence_adapter_base
+{
+public:
+  explicit buffer_sequence_adapter(
+      const asio::mutable_buffers_1& buffers)
+  {
+    init_native_buffer(buffer_, buffers);
+    total_buffer_size_ = asio::buffer_size(buffers);
+  }
+
+  native_buffer_type* buffers()
+  {
+    return &buffer_;
+  }
+
+  std::size_t count() const
+  {
+    return 1;
+  }
+
+  bool all_empty() const
+  {
+    return total_buffer_size_ == 0;
+  }
+
+  static bool all_empty(const asio::mutable_buffers_1& buffers)
+  {
+    return asio::buffer_size(buffers) == 0;
+  }
+
+  static void validate(const asio::mutable_buffers_1& buffers)
+  {
+    asio::buffer_cast<const void*>(buffers);
+  }
+
+  static Buffer first(const asio::mutable_buffers_1& buffers)
+  {
+    return Buffer(buffers);
+  }
+
+private:
+  native_buffer_type buffer_;
+  std::size_t total_buffer_size_;
+};
+
+template <typename Buffer>
+class buffer_sequence_adapter<Buffer, asio::const_buffers_1>
+  : buffer_sequence_adapter_base
+{
+public:
+  explicit buffer_sequence_adapter(
+      const asio::const_buffers_1& buffers)
+  {
+    init_native_buffer(buffer_, buffers);
+    total_buffer_size_ = asio::buffer_size(buffers);
+  }
+
+  native_buffer_type* buffers()
+  {
+    return &buffer_;
+  }
+
+  std::size_t count() const
+  {
+    return 1;
+  }
+
+  bool all_empty() const
+  {
+    return total_buffer_size_ == 0;
+  }
+
+  static bool all_empty(const asio::const_buffers_1& buffers)
+  {
+    return asio::buffer_size(buffers) == 0;
+  }
+
+  static void validate(const asio::const_buffers_1& buffers)
+  {
+    asio::buffer_cast<const void*>(buffers);
+  }
+
+  static Buffer first(const asio::const_buffers_1& buffers)
+  {
+    return Buffer(buffers);
+  }
+
+private:
+  native_buffer_type buffer_;
+  std::size_t total_buffer_size_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP

+ 127 - 0
ext/asio/asio/detail/buffered_stream_storage.hpp

@@ -0,0 +1,127 @@
+//
+// buffered_stream_storage.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_BUFFERED_STREAM_STORAGE_HPP
+#define ASIO_DETAIL_BUFFERED_STREAM_STORAGE_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/config.hpp>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <vector>
+#include "asio/detail/pop_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class buffered_stream_storage
+{
+public:
+  // The type of the bytes stored in the buffer.
+  typedef unsigned char byte_type;
+
+  // The type used for offsets into the buffer.
+  typedef std::size_t size_type;
+
+  // Constructor.
+  explicit buffered_stream_storage(std::size_t capacity)
+    : begin_offset_(0),
+      end_offset_(0),
+      buffer_(capacity)
+  {
+  }
+
+  /// Clear the buffer.
+  void clear()
+  {
+    begin_offset_ = 0;
+    end_offset_ = 0;
+  }
+
+  // Return a pointer to the beginning of the unread data.
+  byte_type* data()
+  {
+    return &buffer_[0] + begin_offset_;
+  }
+
+  // Return a pointer to the beginning of the unread data.
+  const byte_type* data() const
+  {
+    return &buffer_[0] + begin_offset_;
+  }
+
+  // Is there no unread data in the buffer.
+  bool empty() const
+  {
+    return begin_offset_ == end_offset_;
+  }
+
+  // Return the amount of unread data the is in the buffer.
+  size_type size() const
+  {
+    return end_offset_ - begin_offset_;
+  }
+
+  // Resize the buffer to the specified length.
+  void resize(size_type length)
+  {
+    assert(length <= capacity());
+    if (begin_offset_ + length <= capacity())
+    {
+      end_offset_ = begin_offset_ + length;
+    }
+    else
+    {
+      using namespace std; // For memmove.
+      memmove(&buffer_[0], &buffer_[0] + begin_offset_, size());
+      end_offset_ = length;
+      begin_offset_ = 0;
+    }
+  }
+
+  // Return the maximum size for data in the buffer.
+  size_type capacity() const
+  {
+    return buffer_.size();
+  }
+
+  // Consume multiple bytes from the beginning of the buffer.
+  void consume(size_type count)
+  {
+    assert(begin_offset_ + count <= end_offset_);
+    begin_offset_ += count;
+    if (empty())
+      clear();
+  }
+
+private:
+  // The offset to the beginning of the unread data.
+  size_type begin_offset_;
+
+  // The offset to the end of the unread data.
+  size_type end_offset_;
+  
+  // The data in the buffer.
+  std::vector<byte_type> buffer_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP

+ 90 - 0
ext/asio/asio/detail/call_stack.hpp

@@ -0,0 +1,90 @@
+//
+// call_stack.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_CALL_STACK_HPP
+#define ASIO_DETAIL_CALL_STACK_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/noncopyable.hpp"
+#include "asio/detail/tss_ptr.hpp"
+
+namespace asio {
+namespace detail {
+
+// Helper class to determine whether or not the current thread is inside an
+// invocation of io_service::run() for a specified io_service object.
+template <typename Owner>
+class call_stack
+{
+public:
+  // Context class automatically pushes an owner on to the stack.
+  class context
+    : private noncopyable
+  {
+  public:
+    // Push the owner on to the stack.
+    explicit context(Owner* d)
+      : owner_(d),
+        next_(call_stack<Owner>::top_)
+    {
+      call_stack<Owner>::top_ = this;
+    }
+
+    // Pop the owner from the stack.
+    ~context()
+    {
+      call_stack<Owner>::top_ = next_;
+    }
+
+  private:
+    friend class call_stack<Owner>;
+
+    // The owner associated with the context.
+    Owner* owner_;
+
+    // The next element in the stack.
+    context* next_;
+  };
+
+  friend class context;
+
+  // Determine whether the specified owner is on the stack.
+  static bool contains(Owner* d)
+  {
+    context* elem = top_;
+    while (elem)
+    {
+      if (elem->owner_ == d)
+        return true;
+      elem = elem->next_;
+    }
+    return false;
+  }
+
+private:
+  // The top of the stack of calls for the current thread.
+  static tss_ptr<context> top_;
+};
+
+template <typename Owner>
+tss_ptr<typename call_stack<Owner>::context>
+call_stack<Owner>::top_;
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_CALL_STACK_HPP

+ 71 - 0
ext/asio/asio/detail/completion_handler.hpp

@@ -0,0 +1,71 @@
+//
+// completion_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_COMPLETION_HANDLER_HPP
+#define ASIO_DETAIL_COMPLETION_HANDLER_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/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/operation.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class completion_handler : public operation
+{
+public:
+  completion_handler(Handler h)
+    : operation(&completion_handler::do_complete),
+      handler_(h)
+  {
+  }
+
+  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.
+    completion_handler* h(static_cast<completion_handler*>(base));
+    typedef handler_alloc_traits<Handler, completion_handler> alloc_traits;
+    handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      // 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.
+      Handler handler(h->handler_);
+      ptr.reset();
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_COMPLETION_HANDLER_HPP

+ 280 - 0
ext/asio/asio/detail/consuming_buffers.hpp

@@ -0,0 +1,280 @@
+//
+// consuming_buffers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_CONSUMING_BUFFERS_HPP
+#define ASIO_DETAIL_CONSUMING_BUFFERS_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 <algorithm>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/iterator.hpp>
+#include <boost/limits.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/buffer.hpp"
+
+namespace asio {
+namespace detail {
+
+// A proxy iterator for a sub-range in a list of buffers.
+template <typename Buffer, typename Buffer_Iterator>
+class consuming_buffers_iterator
+  : public boost::iterator<std::forward_iterator_tag, const Buffer>
+{
+public:
+  // Default constructor creates an end iterator.
+  consuming_buffers_iterator()
+    : at_end_(true)
+  {
+  }
+
+  // Construct with a buffer for the first entry and an iterator
+  // range for the remaining entries.
+  consuming_buffers_iterator(bool at_end, const Buffer& first,
+      Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
+      std::size_t max_size)
+    : at_end_(max_size > 0 ? at_end : true),
+      first_(buffer(first, max_size)),
+      begin_remainder_(begin_remainder),
+      end_remainder_(end_remainder),
+      offset_(0),
+      max_size_(max_size)
+  {
+  }
+
+  // Dereference an iterator.
+  const Buffer& operator*() const
+  {
+    return dereference();
+  }
+
+  // Dereference an iterator.
+  const Buffer* operator->() const
+  {
+    return &dereference();
+  }
+
+  // Increment operator (prefix).
+  consuming_buffers_iterator& operator++()
+  {
+    increment();
+    return *this;
+  }
+
+  // Increment operator (postfix).
+  consuming_buffers_iterator operator++(int)
+  {
+    consuming_buffers_iterator tmp(*this);
+    ++*this;
+    return tmp;
+  }
+
+  // Test two iterators for equality.
+  friend bool operator==(const consuming_buffers_iterator& a,
+      const consuming_buffers_iterator& b)
+  {
+    return a.equal(b);
+  }
+
+  // Test two iterators for inequality.
+  friend bool operator!=(const consuming_buffers_iterator& a,
+      const consuming_buffers_iterator& b)
+  {
+    return !a.equal(b);
+  }
+
+private:
+  void increment()
+  {
+    if (!at_end_)
+    {
+      if (begin_remainder_ == end_remainder_
+          || offset_ + buffer_size(first_) >= max_size_)
+      {
+        at_end_ = true;
+      }
+      else
+      {
+        offset_ += buffer_size(first_);
+        first_ = buffer(*begin_remainder_++, max_size_ - offset_);
+      }
+    }
+  }
+
+  bool equal(const consuming_buffers_iterator& other) const
+  {
+    if (at_end_ && other.at_end_)
+      return true;
+    return !at_end_ && !other.at_end_
+      && buffer_cast<const void*>(first_)
+        == buffer_cast<const void*>(other.first_)
+      && buffer_size(first_) == buffer_size(other.first_)
+      && begin_remainder_ == other.begin_remainder_
+      && end_remainder_ == other.end_remainder_;
+  }
+
+  const Buffer& dereference() const
+  {
+    return first_;
+  }
+
+  bool at_end_;
+  Buffer first_;
+  Buffer_Iterator begin_remainder_;
+  Buffer_Iterator end_remainder_;
+  std::size_t offset_;
+  std::size_t max_size_;
+};
+
+// A proxy for a sub-range in a list of buffers.
+template <typename Buffer, typename Buffers>
+class consuming_buffers
+{
+public:
+  // The type for each element in the list of buffers.
+  typedef Buffer value_type;
+
+  // A forward-only iterator type that may be used to read elements.
+  typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
+    const_iterator;
+
+  // Construct to represent the entire list of buffers.
+  consuming_buffers(const Buffers& buffers)
+    : buffers_(buffers),
+      at_end_(buffers_.begin() == buffers_.end()),
+      first_(*buffers_.begin()),
+      begin_remainder_(buffers_.begin()),
+      max_size_((std::numeric_limits<std::size_t>::max)())
+  {
+    if (!at_end_)
+      ++begin_remainder_;
+  }
+
+  // Copy constructor.
+  consuming_buffers(const consuming_buffers& other)
+    : buffers_(other.buffers_),
+      at_end_(other.at_end_),
+      first_(other.first_),
+      begin_remainder_(buffers_.begin()),
+      max_size_(other.max_size_)
+  {
+    typename Buffers::const_iterator first = other.buffers_.begin();
+    typename Buffers::const_iterator second = other.begin_remainder_;
+    std::advance(begin_remainder_, std::distance(first, second));
+  }
+
+  // Assignment operator.
+  consuming_buffers& operator=(const consuming_buffers& other)
+  {
+    buffers_ = other.buffers_;
+    at_end_ = other.at_end_;
+    first_ = other.first_;
+    begin_remainder_ = buffers_.begin();
+    typename Buffers::const_iterator first = other.buffers_.begin();
+    typename Buffers::const_iterator second = other.begin_remainder_;
+    std::advance(begin_remainder_, std::distance(first, second));
+    max_size_ = other.max_size_;
+    return *this;
+  }
+
+  // Get a forward-only iterator to the first element.
+  const_iterator begin() const
+  {
+    return const_iterator(at_end_, first_,
+        begin_remainder_, buffers_.end(), max_size_);
+  }
+
+  // Get a forward-only iterator for one past the last element.
+  const_iterator end() const
+  {
+    return const_iterator();
+  }
+
+  // Set the maximum size for a single transfer.
+  void prepare(std::size_t max_size)
+  {
+    max_size_ = max_size;
+  }
+
+  // Consume the specified number of bytes from the buffers.
+  void consume(std::size_t size)
+  {
+    // Remove buffers from the start until the specified size is reached.
+    while (size > 0 && !at_end_)
+    {
+      if (buffer_size(first_) <= size)
+      {
+        size -= buffer_size(first_);
+        if (begin_remainder_ == buffers_.end())
+          at_end_ = true;
+        else
+          first_ = *begin_remainder_++;
+      }
+      else
+      {
+        first_ = first_ + size;
+        size = 0;
+      }
+    }
+
+    // Remove any more empty buffers at the start.
+    while (!at_end_ && buffer_size(first_) == 0)
+    {
+      if (begin_remainder_ == buffers_.end())
+        at_end_ = true;
+      else
+        first_ = *begin_remainder_++;
+    }
+  }
+
+private:
+  Buffers buffers_;
+  bool at_end_;
+  Buffer first_;
+  typename Buffers::const_iterator begin_remainder_;
+  std::size_t max_size_;
+};
+
+// Specialisation for null_buffers to ensure that the null_buffers type is
+// always passed through to the underlying read or write operation.
+template <typename Buffer>
+class consuming_buffers<Buffer, asio::null_buffers>
+  : public asio::null_buffers
+{
+public:
+  consuming_buffers(const asio::null_buffers&)
+  {
+    // No-op.
+  }
+
+  void prepare(std::size_t)
+  {
+    // No-op.
+  }
+
+  void consume(std::size_t)
+  {
+    // No-op.
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP

+ 222 - 0
ext/asio/asio/detail/deadline_timer_service.hpp

@@ -0,0 +1,222 @@
+//
+// deadline_timer_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DEADLINE_TIMER_SERVICE_HPP
+#define ASIO_DETAIL_DEADLINE_TIMER_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 <cstddef>
+#include <boost/config.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/timer_op.hpp"
+#include "asio/detail/timer_queue.hpp"
+#include "asio/detail/timer_scheduler.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+class deadline_timer_service
+{
+public:
+  // The time type.
+  typedef typename Time_Traits::time_type time_type;
+
+  // The duration type.
+  typedef typename Time_Traits::duration_type duration_type;
+
+  // The implementation type of the timer. This type is dependent on the
+  // underlying implementation of the timer service.
+  struct implementation_type
+    : private asio::detail::noncopyable
+  {
+    time_type expiry;
+    bool might_have_pending_waits;
+  };
+
+  // Constructor.
+  deadline_timer_service(asio::io_service& io_service)
+    : scheduler_(asio::use_service<timer_scheduler>(io_service))
+  {
+    scheduler_.init_task();
+    scheduler_.add_timer_queue(timer_queue_);
+  }
+
+  // Destructor.
+  ~deadline_timer_service()
+  {
+    scheduler_.remove_timer_queue(timer_queue_);
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+  }
+
+  // Construct a new timer implementation.
+  void construct(implementation_type& impl)
+  {
+    impl.expiry = time_type();
+    impl.might_have_pending_waits = false;
+  }
+
+  // Destroy a timer implementation.
+  void destroy(implementation_type& impl)
+  {
+    asio::error_code ec;
+    cancel(impl, ec);
+  }
+
+  // Cancel any asynchronous wait operations associated with the timer.
+  std::size_t cancel(implementation_type& impl, asio::error_code& ec)
+  {
+    if (!impl.might_have_pending_waits)
+    {
+      ec = asio::error_code();
+      return 0;
+    }
+    std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
+    impl.might_have_pending_waits = false;
+    ec = asio::error_code();
+    return count;
+  }
+
+  // Get the expiry time for the timer as an absolute time.
+  time_type expires_at(const implementation_type& impl) const
+  {
+    return impl.expiry;
+  }
+
+  // Set the expiry time for the timer as an absolute time.
+  std::size_t expires_at(implementation_type& impl,
+      const time_type& expiry_time, asio::error_code& ec)
+  {
+    std::size_t count = cancel(impl, ec);
+    impl.expiry = expiry_time;
+    ec = asio::error_code();
+    return count;
+  }
+
+  // Get the expiry time for the timer relative to now.
+  duration_type expires_from_now(const implementation_type& impl) const
+  {
+    return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
+  }
+
+  // Set the expiry time for the timer relative to now.
+  std::size_t expires_from_now(implementation_type& impl,
+      const duration_type& expiry_time, asio::error_code& ec)
+  {
+    return expires_at(impl,
+        Time_Traits::add(Time_Traits::now(), expiry_time), ec);
+  }
+
+  // Perform a blocking wait on the timer.
+  void wait(implementation_type& impl, asio::error_code& ec)
+  {
+    time_type now = Time_Traits::now();
+    while (Time_Traits::less_than(now, impl.expiry))
+    {
+      boost::posix_time::time_duration timeout =
+        Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now));
+      ::timeval tv;
+      tv.tv_sec = timeout.total_seconds();
+      tv.tv_usec = timeout.total_microseconds() % 1000000;
+      asio::error_code ec;
+      socket_ops::select(0, 0, 0, 0, &tv, ec);
+      now = Time_Traits::now();
+    }
+    ec = asio::error_code();
+  }
+
+  template <typename Handler>
+  class wait_handler : public timer_op
+  {
+  public:
+    wait_handler(Handler handler)
+      : timer_op(&wait_handler::do_complete),
+        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.
+      wait_handler* h(static_cast<wait_handler*>(base));
+      typedef handler_alloc_traits<Handler, wait_handler> alloc_traits;
+      handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+      // Make the upcall if required.
+      if (owner)
+      {
+        // 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::binder1<Handler, asio::error_code>
+          handler(h->handler_, h->ec_);
+        ptr.reset();
+        asio::detail::fenced_block b;
+        asio_handler_invoke_helpers::invoke(handler, handler);
+      }
+    }
+
+  private:
+    Handler handler_;
+  };
+
+  // Start an asynchronous wait on the timer.
+  template <typename Handler>
+  void async_wait(implementation_type& impl, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef wait_handler<Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+    impl.might_have_pending_waits = true;
+
+    scheduler_.schedule_timer(timer_queue_, impl.expiry, ptr.get(), &impl);
+    ptr.release();
+  }
+
+private:
+  // The queue of timers.
+  timer_queue<Time_Traits> timer_queue_;
+
+  // The object that schedules and executes timers. Usually a reactor.
+  timer_scheduler& scheduler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP

+ 176 - 0
ext/asio/asio/detail/descriptor_ops.hpp

@@ -0,0 +1,176 @@
+//
+// descriptor_ops.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DESCRIPTOR_OPS_HPP
+#define ASIO_DETAIL_DESCRIPTOR_OPS_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/config.hpp>
+#include <cerrno>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/detail/socket_types.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace asio {
+namespace detail {
+namespace descriptor_ops {
+
+inline void clear_error(asio::error_code& ec)
+{
+  errno = 0;
+  ec = asio::error_code();
+}
+
+template <typename ReturnType>
+inline ReturnType error_wrapper(ReturnType return_value,
+    asio::error_code& ec)
+{
+  ec = asio::error_code(errno,
+      asio::error::get_system_category());
+  return return_value;
+}
+
+inline int open(const char* path, int flags, asio::error_code& ec)
+{
+  clear_error(ec);
+  int result = error_wrapper(::open(path, flags), ec);
+  if (result >= 0)
+    clear_error(ec);
+  return result;
+}
+
+inline int close(int d, asio::error_code& ec)
+{
+  clear_error(ec);
+  int result = error_wrapper(::close(d), ec);
+  if (result == 0)
+    clear_error(ec);
+  return result;
+}
+
+inline void init_buf_iov_base(void*& base, void* addr)
+{
+  base = addr;
+}
+
+template <typename T>
+inline void init_buf_iov_base(T& base, void* addr)
+{
+  base = static_cast<T>(addr);
+}
+
+typedef iovec buf;
+
+inline void init_buf(buf& b, void* data, size_t size)
+{
+  init_buf_iov_base(b.iov_base, data);
+  b.iov_len = size;
+}
+
+inline void init_buf(buf& b, const void* data, size_t size)
+{
+  init_buf_iov_base(b.iov_base, const_cast<void*>(data));
+  b.iov_len = size;
+}
+
+inline int scatter_read(int d, buf* bufs, size_t count,
+    asio::error_code& ec)
+{
+  clear_error(ec);
+  int result = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
+  if (result >= 0)
+    clear_error(ec);
+  return result;
+}
+
+inline int gather_write(int d, const buf* bufs, size_t count,
+    asio::error_code& ec)
+{
+  clear_error(ec);
+  int result = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
+  if (result >= 0)
+    clear_error(ec);
+  return result;
+}
+
+inline int ioctl(int d, long cmd, ioctl_arg_type* arg,
+    asio::error_code& ec)
+{
+  clear_error(ec);
+  int result = error_wrapper(::ioctl(d, cmd, arg), ec);
+  if (result >= 0)
+    clear_error(ec);
+  return result;
+}
+
+inline int fcntl(int d, long cmd, asio::error_code& ec)
+{
+  clear_error(ec);
+  int result = error_wrapper(::fcntl(d, cmd), ec);
+  if (result != -1)
+    clear_error(ec);
+  return result;
+}
+
+inline int fcntl(int d, long cmd, long arg, asio::error_code& ec)
+{
+  clear_error(ec);
+  int result = error_wrapper(::fcntl(d, cmd, arg), ec);
+  if (result != -1)
+    clear_error(ec);
+  return result;
+}
+
+inline int poll_read(int d, asio::error_code& ec)
+{
+  clear_error(ec);
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLIN;
+  fds.revents = 0;
+  clear_error(ec);
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    clear_error(ec);
+  return result;
+}
+
+inline int poll_write(int d, asio::error_code& ec)
+{
+  clear_error(ec);
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLOUT;
+  fds.revents = 0;
+  clear_error(ec);
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    clear_error(ec);
+  return result;
+}
+
+} // namespace descriptor_ops
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_DESCRIPTOR_OPS_HPP

+ 453 - 0
ext/asio/asio/detail/dev_poll_reactor.hpp

@@ -0,0 +1,453 @@
+//
+// dev_poll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DEV_POLL_REACTOR_HPP
+#define ASIO_DETAIL_DEV_POLL_REACTOR_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/dev_poll_reactor_fwd.hpp"
+
+#if defined(ASIO_HAS_DEV_POLL)
+
+#include "asio/detail/push_options.hpp"
+#include <cstddef>
+#include <vector>
+#include <boost/config.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/throw_exception.hpp>
+#include <sys/devpoll.h>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/hash_map.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/op_queue.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/reactor_op_queue.hpp"
+#include "asio/detail/select_interrupter.hpp"
+#include "asio/detail/service_base.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/timer_op.hpp"
+#include "asio/detail/timer_queue_base.hpp"
+#include "asio/detail/timer_queue_fwd.hpp"
+#include "asio/detail/timer_queue_set.hpp"
+
+namespace asio {
+namespace detail {
+
+class dev_poll_reactor
+  : public asio::detail::service_base<dev_poll_reactor>
+{
+public:
+  enum { read_op = 0, write_op = 1,
+    connect_op = 1, except_op = 2, max_ops = 3 };
+
+  // Per-descriptor data.
+  struct per_descriptor_data
+  {
+  };
+
+  // Constructor.
+  dev_poll_reactor(asio::io_service& io_service)
+    : asio::detail::service_base<dev_poll_reactor>(io_service),
+      io_service_(use_service<io_service_impl>(io_service)),
+      mutex_(),
+      dev_poll_fd_(do_dev_poll_create()),
+      interrupter_(),
+      shutdown_(false)
+  {
+    // Add the interrupter's descriptor to /dev/poll.
+    ::pollfd ev = { 0 };
+    ev.fd = interrupter_.read_descriptor();
+    ev.events = POLLIN | POLLERR;
+    ev.revents = 0;
+    ::write(dev_poll_fd_, &ev, sizeof(ev));
+  }
+
+  // Destructor.
+  ~dev_poll_reactor()
+  {
+    shutdown_service();
+    ::close(dev_poll_fd_);
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    shutdown_ = true;
+    lock.unlock();
+
+    op_queue<operation> ops;
+
+    for (int i = 0; i < max_ops; ++i)
+      op_queue_[i].get_all_operations(ops);
+
+    timer_queues_.get_all_timers(ops);
+  } 
+
+  // Initialise the task.
+  void init_task()
+  {
+    io_service_.init_task();
+  }
+
+  // Register a socket with the reactor. Returns 0 on success, system error
+  // code on failure.
+  int register_descriptor(socket_type, per_descriptor_data&)
+  {
+    return 0;
+  }
+
+  // Start a new operation. The reactor operation will be performed when the
+  // given descriptor is flagged as ready, or an error has occurred.
+  void start_op(int op_type, socket_type descriptor,
+      per_descriptor_data&, reactor_op* op, bool allow_speculative)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+
+    if (shutdown_)
+      return;
+
+    if (allow_speculative)
+    {
+      if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))
+      {
+        if (!op_queue_[op_type].has_operation(descriptor))
+        {
+          if (op->perform())
+          {
+            lock.unlock();
+            io_service_.post_immediate_completion(op);
+            return;
+          }
+        }
+      }
+    }
+
+    bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+    io_service_.work_started();
+    if (first)
+    {
+      ::pollfd& ev = add_pending_event_change(descriptor);
+      ev.events = POLLERR | POLLHUP;
+      if (op_type == read_op
+          || op_queue_[read_op].has_operation(descriptor))
+        ev.events |= POLLIN;
+      if (op_type == write_op
+          || op_queue_[write_op].has_operation(descriptor))
+        ev.events |= POLLOUT;
+      if (op_type == except_op
+          || op_queue_[except_op].has_operation(descriptor))
+        ev.events |= POLLPRI;
+      interrupter_.interrupt();
+    }
+  }
+
+  // Cancel all operations associated with the given descriptor. The
+  // handlers associated with the descriptor will be invoked with the
+  // operation_aborted error.
+  void cancel_ops(socket_type descriptor, per_descriptor_data&)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+  }
+
+  // Cancel any operations that are running against the descriptor and remove
+  // its registration from the reactor.
+  void close_descriptor(socket_type descriptor, per_descriptor_data&)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+
+    // Remove the descriptor from /dev/poll.
+    ::pollfd& ev = add_pending_event_change(descriptor);
+    ev.events = POLLREMOVE;
+    interrupter_.interrupt();
+
+    // Cancel any outstanding operations associated with the descriptor.
+    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+  }
+
+  // Add a new timer queue to the reactor.
+  template <typename Time_Traits>
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    timer_queues_.insert(&timer_queue);
+  }
+
+  // Remove a timer queue from the reactor.
+  template <typename Time_Traits>
+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    timer_queues_.erase(&timer_queue);
+  }
+
+  // Schedule a new operation in the given timer queue to expire at the
+  // specified absolute time.
+  template <typename Time_Traits>
+  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+      const typename Time_Traits::time_type& time, timer_op* op, void* token)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    if (!shutdown_)
+    {
+      bool earliest = timer_queue.enqueue_timer(time, op, token);
+      io_service_.work_started();
+      if (earliest)
+        interrupter_.interrupt();
+    }
+  }
+
+  // Cancel the timer operations associated with the given token. Returns the
+  // number of operations that have been posted or dispatched.
+  template <typename Time_Traits>
+  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    op_queue<operation> ops;
+    std::size_t n = timer_queue.cancel_timer(token, ops);
+    lock.unlock();
+    io_service_.post_deferred_completions(ops);
+    return n;
+  }
+
+  // Run /dev/poll once until interrupted or events are ready to be dispatched.
+  void run(bool block, op_queue<operation>& ops)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+
+    // We can return immediately if there's no work to do and the reactor is
+    // not supposed to block.
+    if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
+        && op_queue_[except_op].empty() && timer_queues_.all_empty())
+      return;
+
+    // Write the pending event registration changes to the /dev/poll descriptor.
+    std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
+    if (events_size > 0)
+    {
+      errno = 0;
+      int result = ::write(dev_poll_fd_,
+          &pending_event_changes_[0], events_size);
+      if (result != static_cast<int>(events_size))
+      {
+        asio::error_code ec = asio::error_code(
+            errno, asio::error::get_system_category());
+        for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
+        {
+          int descriptor = pending_event_changes_[i].fd;
+          for (int j = 0; j < max_ops; ++j)
+            op_queue_[j].cancel_operations(descriptor, ops, ec);
+        }
+      }
+      pending_event_changes_.clear();
+      pending_event_change_index_.clear();
+    }
+
+    int timeout = block ? get_timeout() : 0;
+    lock.unlock();
+
+    // Block on the /dev/poll descriptor.
+    ::pollfd events[128] = { { 0 } };
+    ::dvpoll dp = { 0 };
+    dp.dp_fds = events;
+    dp.dp_nfds = 128;
+    dp.dp_timeout = timeout;
+    int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
+
+    lock.lock();
+
+    // Dispatch the waiting events.
+    for (int i = 0; i < num_events; ++i)
+    {
+      int descriptor = events[i].fd;
+      if (descriptor == interrupter_.read_descriptor())
+      {
+        interrupter_.reset();
+      }
+      else
+      {
+        bool more_reads = false;
+        bool more_writes = false;
+        bool more_except = false;
+
+        // Exception operations must be processed first to ensure that any
+        // out-of-band data is read before normal data.
+        if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
+          more_except =
+            op_queue_[except_op].perform_operations(descriptor, ops);
+        else
+          more_except = op_queue_[except_op].has_operation(descriptor);
+
+        if (events[i].events & (POLLIN | POLLERR | POLLHUP))
+          more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
+        else
+          more_reads = op_queue_[read_op].has_operation(descriptor);
+
+        if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
+          more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
+        else
+          more_writes = op_queue_[write_op].has_operation(descriptor);
+
+        if ((events[i].events & (POLLERR | POLLHUP)) != 0
+              && !more_except && !more_reads && !more_writes)
+        {
+          // If we have an event and no operations associated with the
+          // descriptor then we need to delete the descriptor from /dev/poll.
+          // The poll operation can produce POLLHUP or POLLERR events when there
+          // is no operation pending, so if we do not remove the descriptor we
+          // can end up in a tight polling loop.
+          ::pollfd ev = { 0 };
+          ev.fd = descriptor;
+          ev.events = POLLREMOVE;
+          ev.revents = 0;
+          ::write(dev_poll_fd_, &ev, sizeof(ev));
+        }
+        else
+        {
+          ::pollfd ev = { 0 };
+          ev.fd = descriptor;
+          ev.events = POLLERR | POLLHUP;
+          if (more_reads)
+            ev.events |= POLLIN;
+          if (more_writes)
+            ev.events |= POLLOUT;
+          if (more_except)
+            ev.events |= POLLPRI;
+          ev.revents = 0;
+          int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
+          if (result != sizeof(ev))
+          {
+            asio::error_code ec(errno,
+                asio::error::get_system_category());
+            for (int j = 0; j < max_ops; ++j)
+              op_queue_[j].cancel_operations(descriptor, ops, ec);
+          }
+        }
+      }
+    }
+    timer_queues_.get_ready_timers(ops);
+  }
+
+  // Interrupt the select loop.
+  void interrupt()
+  {
+    interrupter_.interrupt();
+  }
+
+private:
+  // Create the /dev/poll file descriptor. Throws an exception if the descriptor
+  // cannot be created.
+  static int do_dev_poll_create()
+  {
+    int fd = ::open("/dev/poll", O_RDWR);
+    if (fd == -1)
+    {
+      boost::throw_exception(
+          asio::system_error(
+            asio::error_code(errno,
+              asio::error::get_system_category()),
+            "/dev/poll"));
+    }
+    return fd;
+  }
+
+  // Get the timeout value for the /dev/poll DP_POLL operation. The timeout
+  // value is returned as a number of milliseconds. A return value of -1
+  // indicates that the poll should block indefinitely.
+  int get_timeout()
+  {
+    // By default we will wait no longer than 5 minutes. This will ensure that
+    // any changes to the system clock are detected after no longer than this.
+    return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+  }
+
+  // Cancel all operations associated with the given descriptor. The do_cancel
+  // function of the handler objects will be invoked. This function does not
+  // acquire the dev_poll_reactor's mutex.
+  void cancel_ops_unlocked(socket_type descriptor,
+      const asio::error_code& ec)
+  {
+    bool need_interrupt = false;
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+      need_interrupt = op_queue_[i].cancel_operations(
+          descriptor, ops, ec) || need_interrupt;
+    io_service_.post_deferred_completions(ops);
+    if (need_interrupt)
+      interrupter_.interrupt();
+  }
+
+  // Add a pending event entry for the given descriptor.
+  ::pollfd& add_pending_event_change(int descriptor)
+  {
+    hash_map<int, std::size_t>::iterator iter
+      = pending_event_change_index_.find(descriptor);
+    if (iter == pending_event_change_index_.end())
+    {
+      std::size_t index = pending_event_changes_.size();
+      pending_event_changes_.reserve(pending_event_changes_.size() + 1);
+      pending_event_change_index_.insert(std::make_pair(descriptor, index));
+      pending_event_changes_.push_back(::pollfd());
+      pending_event_changes_[index].fd = descriptor;
+      pending_event_changes_[index].revents = 0;
+      return pending_event_changes_[index];
+    }
+    else
+    {
+      return pending_event_changes_[iter->second];
+    }
+  }
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_;
+
+  // Mutex to protect access to internal data.
+  asio::detail::mutex mutex_;
+
+  // The /dev/poll file descriptor.
+  int dev_poll_fd_;
+
+  // Vector of /dev/poll events waiting to be written to the descriptor.
+  std::vector< ::pollfd> pending_event_changes_;
+
+  // Hash map to associate a descriptor with a pending event change index.
+  hash_map<int, std::size_t> pending_event_change_index_;
+
+  // The interrupter is used to break a blocking DP_POLL operation.
+  select_interrupter interrupter_;
+
+  // The queues of read, write and except operations.
+  reactor_op_queue<socket_type> op_queue_[max_ops];
+
+  // The timer queues.
+  timer_queue_set timer_queues_;
+
+  // Whether the service has been shut down.
+  bool shutdown_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(ASIO_HAS_DEV_POLL)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_DEV_POLL_REACTOR_HPP

+ 39 - 0
ext/asio/asio/detail/dev_poll_reactor_fwd.hpp

@@ -0,0 +1,39 @@
+//
+// dev_poll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DEV_POLL_REACTOR_FWD_HPP
+#define ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+#if !defined(ASIO_DISABLE_DEV_POLL)
+#if defined(__sun) // This service is only supported on Solaris.
+
+// Define this to indicate that /dev/poll is supported on the target platform.
+#define ASIO_HAS_DEV_POLL 1
+
+namespace asio {
+namespace detail {
+
+class dev_poll_reactor;
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(__sun)
+#endif // !defined(ASIO_DISABLE_DEV_POLL)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP

+ 507 - 0
ext/asio/asio/detail/epoll_reactor.hpp

@@ -0,0 +1,507 @@
+//
+// epoll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_EPOLL_REACTOR_HPP
+#define ASIO_DETAIL_EPOLL_REACTOR_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/epoll_reactor_fwd.hpp"
+
+#if defined(ASIO_HAS_EPOLL)
+
+#include "asio/detail/push_options.hpp"
+#include <cstddef>
+#include <sys/epoll.h>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/hash_map.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/op_queue.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/select_interrupter.hpp"
+#include "asio/detail/service_base.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/timer_op.hpp"
+#include "asio/detail/timer_queue_base.hpp"
+#include "asio/detail/timer_queue_fwd.hpp"
+#include "asio/detail/timer_queue_set.hpp"
+
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+# define ASIO_HAS_TIMERFD 1
+#endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+
+#if defined(ASIO_HAS_TIMERFD)
+# include "asio/detail/push_options.hpp"
+# include <sys/timerfd.h>
+# include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_TIMERFD)
+
+namespace asio {
+namespace detail {
+
+class epoll_reactor
+  : public asio::detail::service_base<epoll_reactor>
+{
+public:
+  enum { read_op = 0, write_op = 1,
+    connect_op = 1, except_op = 2, max_ops = 3 };
+
+  // Per-descriptor queues.
+  struct descriptor_state
+  {
+    descriptor_state() {}
+    descriptor_state(const descriptor_state&) {}
+    void operator=(const descriptor_state&) {}
+
+    mutex mutex_;
+    op_queue<reactor_op> op_queue_[max_ops];
+    bool shutdown_;
+  };
+
+  // Per-descriptor data.
+  typedef descriptor_state* per_descriptor_data;
+
+  // Constructor.
+  epoll_reactor(asio::io_service& io_service)
+    : asio::detail::service_base<epoll_reactor>(io_service),
+      io_service_(use_service<io_service_impl>(io_service)),
+      mutex_(),
+      epoll_fd_(do_epoll_create()),
+#if defined(ASIO_HAS_TIMERFD)
+      timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)),
+#else // defined(ASIO_HAS_TIMERFD)
+      timer_fd_(-1),
+#endif // defined(ASIO_HAS_TIMERFD)
+      interrupter_(),
+      shutdown_(false)
+  {
+    // Add the interrupter's descriptor to epoll.
+    epoll_event ev = { 0, { 0 } };
+    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+    ev.data.ptr = &interrupter_;
+    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
+    interrupter_.interrupt();
+
+    // Add the timer descriptor to epoll.
+    if (timer_fd_ != -1)
+    {
+      ev.events = EPOLLIN | EPOLLERR;
+      ev.data.ptr = &timer_fd_;
+      epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
+    }
+  }
+
+  // Destructor.
+  ~epoll_reactor()
+  {
+    close(epoll_fd_);
+    if (timer_fd_ != -1)
+      close(timer_fd_);
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    mutex::scoped_lock lock(mutex_);
+    shutdown_ = true;
+    lock.unlock();
+
+    op_queue<operation> ops;
+
+    descriptor_map::iterator iter = registered_descriptors_.begin();
+    descriptor_map::iterator end = registered_descriptors_.end();
+    while (iter != end)
+    {
+      for (int i = 0; i < max_ops; ++i)
+        ops.push(iter->second.op_queue_[i]);
+      iter->second.shutdown_ = true;
+      ++iter;
+    }
+
+    timer_queues_.get_all_timers(ops);
+  }
+
+  // Initialise the task.
+  void init_task()
+  {
+    io_service_.init_task();
+  }
+
+  // Register a socket with the reactor. Returns 0 on success, system error
+  // code on failure.
+  int register_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data)
+  {
+    mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+    descriptor_map::iterator new_entry = registered_descriptors_.insert(
+          std::make_pair(descriptor, descriptor_state())).first;
+    descriptor_data = &new_entry->second;
+
+    epoll_event ev = { 0, { 0 } };
+    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
+    ev.data.ptr = descriptor_data;
+    int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+    if (result != 0)
+      return errno;
+
+    descriptor_data->shutdown_ = false;
+
+    return 0;
+  }
+
+  // Start a new operation. The reactor operation will be performed when the
+  // given descriptor is flagged as ready, or an error has occurred.
+  void start_op(int op_type, socket_type descriptor,
+      per_descriptor_data& descriptor_data,
+      reactor_op* op, bool allow_speculative)
+  {
+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+    if (descriptor_data->shutdown_)
+      return;
+
+    if (descriptor_data->op_queue_[op_type].empty())
+    {
+      if (allow_speculative
+          && (op_type != read_op
+            || descriptor_data->op_queue_[except_op].empty()))
+      {
+        if (op->perform())
+        {
+          descriptor_lock.unlock();
+          io_service_.post_immediate_completion(op);
+          return;
+        }
+      }
+      else
+      {
+        epoll_event ev = { 0, { 0 } };
+        ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
+          | EPOLLOUT | EPOLLPRI | EPOLLET;
+        ev.data.ptr = descriptor_data;
+        epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+      }
+    }
+
+    descriptor_data->op_queue_[op_type].push(op);
+    io_service_.work_started();
+  }
+
+  // Cancel all operations associated with the given descriptor. The
+  // handlers associated with the descriptor will be invoked with the
+  // operation_aborted error.
+  void cancel_ops(socket_type descriptor, per_descriptor_data& descriptor_data)
+  {
+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+
+  // Cancel any operations that are running against the descriptor and remove
+  // its registration from the reactor.
+  void close_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data)
+  {
+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
+
+    // Remove the descriptor from the set of known descriptors. The descriptor
+    // will be automatically removed from the epoll set when it is closed.
+    descriptor_data->shutdown_ = true;
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_lock.unlock();
+
+    registered_descriptors_.erase(descriptor);
+
+    descriptors_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+
+  // Add a new timer queue to the reactor.
+  template <typename Time_Traits>
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    mutex::scoped_lock lock(mutex_);
+    timer_queues_.insert(&timer_queue);
+  }
+
+  // Remove a timer queue from the reactor.
+  template <typename Time_Traits>
+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    mutex::scoped_lock lock(mutex_);
+    timer_queues_.erase(&timer_queue);
+  }
+
+  // Schedule a new operation in the given timer queue to expire at the
+  // specified absolute time.
+  template <typename Time_Traits>
+  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+      const typename Time_Traits::time_type& time, timer_op* op, void* token)
+  {
+    mutex::scoped_lock lock(mutex_);
+    if (!shutdown_)
+    {
+      bool earliest = timer_queue.enqueue_timer(time, op, token);
+      io_service_.work_started();
+      if (earliest)
+      {
+#if defined(ASIO_HAS_TIMERFD)
+        if (timer_fd_ != -1)
+        {
+          itimerspec new_timeout;
+          itimerspec old_timeout;
+          int flags = get_timeout(new_timeout);
+          timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+          return;
+        }
+#endif // defined(ASIO_HAS_TIMERFD)
+        interrupter_.interrupt();
+      }
+    }
+  }
+
+  // Cancel the timer operations associated with the given token. Returns the
+  // number of operations that have been posted or dispatched.
+  template <typename Time_Traits>
+  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+  {
+    mutex::scoped_lock lock(mutex_);
+    op_queue<operation> ops;
+    std::size_t n = timer_queue.cancel_timer(token, ops);
+    lock.unlock();
+    io_service_.post_deferred_completions(ops);
+    return n;
+  }
+
+  // Run epoll once until interrupted or events are ready to be dispatched.
+  void run(bool block, op_queue<operation>& ops)
+  {
+    // Calculate a timeout only if timerfd is not used.
+    int timeout;
+    if (timer_fd_ != -1)
+      timeout = block ? -1 : 0;
+    else
+    {
+      mutex::scoped_lock lock(mutex_);
+      timeout = block ? get_timeout() : 0;
+    }
+
+    // Block on the epoll descriptor.
+    epoll_event events[128];
+    int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
+
+#if defined(ASIO_HAS_TIMERFD)
+    bool check_timers = (timer_fd_ == -1);
+#else // defined(ASIO_HAS_TIMERFD)
+    bool check_timers = true;
+#endif // defined(ASIO_HAS_TIMERFD)
+
+    // Dispatch the waiting events.
+    for (int i = 0; i < num_events; ++i)
+    {
+      void* ptr = events[i].data.ptr;
+      if (ptr == &interrupter_)
+      {
+        // No need to reset the interrupter since we're leaving the descriptor
+        // in a ready-to-read state and relying on edge-triggered notifications
+        // to make it so that we only get woken up when the descriptor's epoll
+        // registration is updated.
+
+#if defined(ASIO_HAS_TIMERFD)
+        if (timer_fd_ == -1)
+          check_timers = true;
+#else // defined(ASIO_HAS_TIMERFD)
+        check_timers = true;
+#endif // defined(ASIO_HAS_TIMERFD)
+      }
+#if defined(ASIO_HAS_TIMERFD)
+      else if (ptr == &timer_fd_)
+      {
+        check_timers = true;
+      }
+#endif // defined(ASIO_HAS_TIMERFD)
+      else
+      {
+        descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
+        mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+        // Exception operations must be processed first to ensure that any
+        // out-of-band data is read before normal data.
+        static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
+        for (int j = max_ops - 1; j >= 0; --j)
+        {
+          if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))
+          {
+            while (reactor_op* op = descriptor_data->op_queue_[j].front())
+            {
+              if (op->perform())
+              {
+                descriptor_data->op_queue_[j].pop();
+                ops.push(op);
+              }
+              else
+                break;
+            }
+          }
+        }
+      }
+    }
+
+    if (check_timers)
+    {
+      mutex::scoped_lock common_lock(mutex_);
+      timer_queues_.get_ready_timers(ops);
+
+#if defined(ASIO_HAS_TIMERFD)
+      if (timer_fd_ != -1)
+      {
+        itimerspec new_timeout;
+        itimerspec old_timeout;
+        int flags = get_timeout(new_timeout);
+        timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+      }
+#endif // defined(ASIO_HAS_TIMERFD)
+    }
+  }
+
+  // Interrupt the select loop.
+  void interrupt()
+  {
+    epoll_event ev = { 0, { 0 } };
+    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+    ev.data.ptr = &interrupter_;
+    epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
+  }
+
+private:
+  // The hint to pass to epoll_create to size its data structures.
+  enum { epoll_size = 20000 };
+
+  // Create the epoll file descriptor. Throws an exception if the descriptor
+  // cannot be created.
+  static int do_epoll_create()
+  {
+    int fd = epoll_create(epoll_size);
+    if (fd == -1)
+    {
+      boost::throw_exception(
+          asio::system_error(
+            asio::error_code(errno,
+              asio::error::get_system_category()),
+            "epoll"));
+    }
+    return fd;
+  }
+
+  // Get the timeout value for the epoll_wait call. The timeout value is
+  // returned as a number of milliseconds. A return value of -1 indicates
+  // that epoll_wait should block indefinitely.
+  int get_timeout()
+  {
+    // By default we will wait no longer than 5 minutes. This will ensure that
+    // any changes to the system clock are detected after no longer than this.
+    return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+  }
+
+#if defined(ASIO_HAS_TIMERFD)
+  // Get the timeout value for the timer descriptor. The return value is the
+  // flag argument to be used when calling timerfd_settime.
+  int get_timeout(itimerspec& ts)
+  {
+    ts.it_interval.tv_sec = 0;
+    ts.it_interval.tv_nsec = 0;
+
+    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+    ts.it_value.tv_sec = usec / 1000000;
+    ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
+
+    return usec ? 0 : TFD_TIMER_ABSTIME;
+  }
+#endif // defined(ASIO_HAS_TIMERFD)
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_;
+
+  // Mutex to protect access to internal data.
+  mutex mutex_;
+
+  // The epoll file descriptor.
+  int epoll_fd_;
+
+  // The timer file descriptor.
+  int timer_fd_;
+
+  // The interrupter is used to break a blocking epoll_wait call.
+  select_interrupter interrupter_;
+
+  // The timer queues.
+  timer_queue_set timer_queues_;
+
+  // Whether the service has been shut down.
+  bool shutdown_;
+
+  // Mutex to protect access to the registered descriptors.
+  mutex registered_descriptors_mutex_;
+
+  // Keep track of all registered descriptors. This code relies on the fact that
+  // the hash_map implementation pools deleted nodes, meaning that we can assume
+  // our descriptor_state pointer remains valid even after the entry is removed.
+  // Technically this is not true for C++98, as that standard says that spliced
+  // elements in a list are invalidated. However, C++0x fixes this shortcoming
+  // so we'll just assume that C++98 std::list implementations will do the right
+  // thing anyway.
+  typedef detail::hash_map<socket_type, descriptor_state> descriptor_map;
+  descriptor_map registered_descriptors_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(ASIO_HAS_EPOLL)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_EPOLL_REACTOR_HPP

+ 46 - 0
ext/asio/asio/detail/epoll_reactor_fwd.hpp

@@ -0,0 +1,46 @@
+//
+// epoll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_EPOLL_REACTOR_FWD_HPP
+#define ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+#if !defined(ASIO_DISABLE_EPOLL)
+#if defined(__linux__) // This service is only supported on Linux.
+
+#include "asio/detail/push_options.hpp"
+#include <linux/version.h>
+#include "asio/detail/pop_options.hpp"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45.
+
+// Define this to indicate that epoll is supported on the target platform.
+#define ASIO_HAS_EPOLL 1
+
+namespace asio {
+namespace detail {
+
+class epoll_reactor;
+
+} // namespace detail
+} // namespace asio
+
+#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45)
+#endif // defined(__linux__)
+#endif // !defined(ASIO_DISABLE_EPOLL)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP

+ 50 - 0
ext/asio/asio/detail/event.hpp

@@ -0,0 +1,50 @@
+//
+// event.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_EVENT_HPP
+#define ASIO_DETAIL_EVENT_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+# include "asio/detail/null_event.hpp"
+#elif defined(BOOST_WINDOWS)
+# include "asio/detail/win_event.hpp"
+#elif defined(BOOST_HAS_PTHREADS)
+# include "asio/detail/posix_event.hpp"
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+typedef null_event event;
+#elif defined(BOOST_WINDOWS)
+typedef win_event event;
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_event event;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_EVENT_HPP

+ 166 - 0
ext/asio/asio/detail/eventfd_select_interrupter.hpp

@@ -0,0 +1,166 @@
+//
+// eventfd_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail 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_EVENTFD_SELECT_INTERRUPTER_HPP
+#define ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_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/config.hpp>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(__linux__)
+# if !defined(ASIO_DISABLE_EVENTFD)
+#  include <linux/version.h>
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+#   define ASIO_HAS_EVENTFD
+#  endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+# endif // !defined(ASIO_DISABLE_EVENTFD)
+#endif // defined(__linux__)
+
+#if defined(ASIO_HAS_EVENTFD)
+
+#include "asio/detail/push_options.hpp"
+#include <fcntl.h>
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+# include <asm/unistd.h>
+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+# include <sys/eventfd.h>
+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/socket_types.hpp"
+
+namespace asio {
+namespace detail {
+
+class eventfd_select_interrupter
+{
+public:
+  // Constructor.
+  eventfd_select_interrupter()
+  {
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+    write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+    write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+    if (read_descriptor_ != -1)
+    {
+      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+    }
+    else
+    {
+      int pipe_fds[2];
+      if (pipe(pipe_fds) == 0)
+      {
+        read_descriptor_ = pipe_fds[0];
+        ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+        write_descriptor_ = pipe_fds[1];
+        ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+      }
+      else
+      {
+        asio::error_code ec(errno,
+            asio::error::get_system_category());
+        asio::system_error e(ec, "eventfd_select_interrupter");
+        boost::throw_exception(e);
+      }
+    }
+  }
+
+  // Destructor.
+  ~eventfd_select_interrupter()
+  {
+    if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
+      ::close(write_descriptor_);
+    if (read_descriptor_ != -1)
+      ::close(read_descriptor_);
+  }
+
+  // Interrupt the select call.
+  void interrupt()
+  {
+    uint64_t counter(1UL);
+    int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
+    (void)result;
+  }
+
+  // Reset the select interrupt. Returns true if the call was interrupted.
+  bool reset()
+  {
+    if (write_descriptor_ == read_descriptor_)
+    {
+      for (;;)
+      {
+        // Only perform one read. The kernel maintains an atomic counter.
+        uint64_t counter(0);
+        errno = 0;
+        int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
+        if (bytes_read < 0 && errno == EINTR)
+          continue;
+        bool was_interrupted = (bytes_read > 0);
+        return was_interrupted;
+      }
+    }
+    else
+    {
+      for (;;)
+      {
+        // Clear all data from the pipe.
+        char data[1024];
+        int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+        if (bytes_read < 0 && errno == EINTR)
+          continue;
+        bool was_interrupted = (bytes_read > 0);
+        while (bytes_read == sizeof(data))
+          bytes_read = ::read(read_descriptor_, data, sizeof(data));
+        return was_interrupted;
+      }
+    }
+  }
+
+  // Get the read descriptor to be passed to select.
+  int read_descriptor() const
+  {
+    return read_descriptor_;
+  }
+
+private:
+  // The read end of a connection used to interrupt the select call. This file
+  // descriptor is passed to select such that when it is time to stop, a single
+  // 64bit value will be written on the other end of the connection and this
+  // descriptor will become readable.
+  int read_descriptor_;
+
+  // The write end of a connection used to interrupt the select call. A single
+  // 64bit non-zero value may be written to this to wake up the select which is
+  // waiting for the other end to become readable. This descriptor will only
+  // differ from the read descriptor when a pipe is used.
+  int write_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(ASIO_HAS_EVENTFD)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP

+ 41 - 0
ext/asio/asio/detail/fd_set_adapter.hpp

@@ -0,0 +1,41 @@
+//
+// fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_FD_SET_ADAPTER_HPP
+#define ASIO_DETAIL_FD_SET_ADAPTER_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/posix_fd_set_adapter.hpp"
+#include "asio/detail/win_fd_set_adapter.hpp"
+
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef win_fd_set_adapter fd_set_adapter;
+#else
+typedef posix_fd_set_adapter fd_set_adapter;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP

+ 70 - 0
ext/asio/asio/detail/fenced_block.hpp

@@ -0,0 +1,70 @@
+//
+// fenced_block.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_FENCED_BLOCK_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+# include "asio/detail/null_fenced_block.hpp"
+#elif defined(__MACH__) && defined(__APPLE__)
+# include "asio/detail/macos_fenced_block.hpp"
+#elif defined(__sun)
+# include "asio/detail/solaris_fenced_block.hpp"
+#elif defined(__GNUC__) \
+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \
+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+# include "asio/detail/gcc_fenced_block.hpp"
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+# include "asio/detail/gcc_x86_fenced_block.hpp"
+#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+# include "asio/detail/win_fenced_block.hpp"
+#else
+# include "asio/detail/null_fenced_block.hpp"
+#endif
+
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+typedef null_fenced_block fenced_block;
+#elif defined(__MACH__) && defined(__APPLE__)
+typedef macos_fenced_block fenced_block;
+#elif defined(__sun)
+typedef solaris_fenced_block fenced_block;
+#elif defined(__GNUC__) \
+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \
+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+typedef gcc_fenced_block fenced_block;
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+typedef gcc_x86_fenced_block fenced_block;
+#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+typedef win_fenced_block fenced_block;
+#else
+typedef null_fenced_block fenced_block;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_FENCED_BLOCK_HPP

+ 63 - 0
ext/asio/asio/detail/gcc_fenced_block.hpp

@@ -0,0 +1,63 @@
+//
+// gcc_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_GCC_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_FENCED_BLOCK_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(__GNUC__) \
+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \
+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+
+namespace asio {
+namespace detail {
+
+class gcc_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_fenced_block()
+    : value_(0)
+  {
+    __sync_lock_test_and_set(&value_, 1);
+  }
+
+  // Destructor.
+  ~gcc_fenced_block()
+  {
+    __sync_lock_release(&value_);
+  }
+
+private:
+  int value_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(__GNUC__)
+       // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4))
+       // && !defined(__INTEL_COMPILER) && !defined(__ICL)
+       // && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_GCC_FENCED_BLOCK_HPP

+ 61 - 0
ext/asio/asio/detail/gcc_x86_fenced_block.hpp

@@ -0,0 +1,61 @@
+//
+// gcc_x86_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_GCC_X86_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_X86_FENCED_BLOCK_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+namespace asio {
+namespace detail {
+
+class gcc_x86_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_x86_fenced_block()
+  {
+    barrier();
+  }
+
+  // Destructor.
+  ~gcc_x86_fenced_block()
+  {
+    barrier();
+  }
+
+private:
+  static int barrier()
+  {
+    int r = 0;
+    __asm__ __volatile__ ("xchgl %%eax, %0" : "=m" (r) : : "memory", "cc");
+    return r;
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP

+ 259 - 0
ext/asio/asio/detail/handler_alloc_helpers.hpp

@@ -0,0 +1,259 @@
+//
+// handler_alloc_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_HANDLER_ALLOC_HELPERS_HPP
+#define ASIO_DETAIL_HANDLER_ALLOC_HELPERS_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/detail/workaround.hpp>
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/handler_alloc_hook.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+// Calls to asio_handler_allocate and asio_handler_deallocate must be made from
+// a namespace that does not contain any overloads of these functions. The
+// asio_handler_alloc_helpers namespace is defined here for that purpose.
+namespace asio_handler_alloc_helpers {
+
+template <typename Handler>
+inline void* allocate(std::size_t s, Handler& h)
+{
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
+  || BOOST_WORKAROUND(__GNUC__, < 3)
+  return ::operator new(s);
+#else
+  using namespace asio;
+  return asio_handler_allocate(s, boost::addressof(h));
+#endif
+}
+
+template <typename Handler>
+inline void deallocate(void* p, std::size_t s, Handler& h)
+{
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
+  || BOOST_WORKAROUND(__GNUC__, < 3)
+  ::operator delete(p);
+#else
+  using namespace asio;
+  asio_handler_deallocate(p, s, boost::addressof(h));
+#endif
+}
+
+} // namespace asio_handler_alloc_helpers
+
+namespace asio {
+namespace detail {
+
+// Traits for handler allocation.
+template <typename Handler, typename Object>
+struct handler_alloc_traits
+{
+  typedef Handler handler_type;
+  typedef Object value_type;
+  typedef Object* pointer_type;
+  BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object));
+};
+
+template <typename Alloc_Traits>
+class handler_ptr;
+
+// Helper class to provide RAII on uninitialised handler memory.
+template <typename Alloc_Traits>
+class raw_handler_ptr
+  : private noncopyable
+{
+public:
+  typedef typename Alloc_Traits::handler_type handler_type;
+  typedef typename Alloc_Traits::value_type value_type;
+  typedef typename Alloc_Traits::pointer_type pointer_type;
+  BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
+
+  // Constructor allocates the memory.
+  raw_handler_ptr(handler_type& handler)
+    : handler_(handler),
+      pointer_(static_cast<pointer_type>(
+            asio_handler_alloc_helpers::allocate(value_size, handler_)))
+  {
+  }
+
+  // Destructor automatically deallocates memory, unless it has been stolen by
+  // a handler_ptr object.
+  ~raw_handler_ptr()
+  {
+    if (pointer_)
+      asio_handler_alloc_helpers::deallocate(
+          pointer_, value_size, handler_);
+  }
+
+private:
+  friend class handler_ptr<Alloc_Traits>;
+  handler_type& handler_;
+  pointer_type pointer_;
+};
+
+// Helper class to provide RAII on uninitialised handler memory.
+template <typename Alloc_Traits>
+class handler_ptr
+  : private noncopyable
+{
+public:
+  typedef typename Alloc_Traits::handler_type handler_type;
+  typedef typename Alloc_Traits::value_type value_type;
+  typedef typename Alloc_Traits::pointer_type pointer_type;
+  BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
+  typedef raw_handler_ptr<Alloc_Traits> raw_ptr_type;
+
+  // Take ownership of existing memory.
+  handler_ptr(handler_type& handler, pointer_type pointer)
+    : handler_(handler),
+      pointer_(pointer)
+  {
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  handler_ptr(raw_ptr_type& raw_ptr)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type)
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(a1))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1, typename Arg2>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(a1, a2))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1, typename Arg2, typename Arg3>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+      typename Arg5>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
+      Arg5& a5)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+      typename Arg5, typename Arg6>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
+      Arg5& a5, Arg6& a6)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+      typename Arg5, typename Arg6, typename Arg7>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
+      Arg5& a5, Arg6& a6, Arg7& a7)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Construct object in raw memory and take ownership if construction succeeds.
+  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+      typename Arg5, typename Arg6, typename Arg7, typename Arg8>
+  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
+      Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8)
+    : handler_(raw_ptr.handler_),
+      pointer_(new (raw_ptr.pointer_) value_type(
+            a1, a2, a3, a4, a5, a6, a7, a8))
+  {
+    raw_ptr.pointer_ = 0;
+  }
+
+  // Destructor automatically deallocates memory, unless it has been released.
+  ~handler_ptr()
+  {
+    reset();
+  }
+
+  // Get the memory.
+  pointer_type get() const
+  {
+    return pointer_;
+  }
+
+  // Release ownership of the memory.
+  pointer_type release()
+  {
+    pointer_type tmp = pointer_;
+    pointer_ = 0;
+    return tmp;
+  }
+
+  // Explicitly destroy and deallocate the memory.
+  void reset()
+  {
+    if (pointer_)
+    {
+      pointer_->value_type::~value_type();
+      asio_handler_alloc_helpers::deallocate(
+          pointer_, value_size, handler_);
+      pointer_ = 0;
+    }
+  }
+
+private:
+  handler_type& handler_;
+  pointer_type pointer_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP

+ 49 - 0
ext/asio/asio/detail/handler_invoke_helpers.hpp

@@ -0,0 +1,49 @@
+//
+// handler_invoke_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_HANDLER_INVOKE_HELPERS_HPP
+#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_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/detail/workaround.hpp>
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/handler_invoke_hook.hpp"
+
+// Calls to asio_handler_invoke must be made from a namespace that does not
+// contain overloads of this function. The asio_handler_invoke_helpers
+// namespace is defined here for that purpose.
+namespace asio_handler_invoke_helpers {
+
+template <typename Function, typename Context>
+inline void invoke(const Function& function, Context& context)
+{
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
+  || BOOST_WORKAROUND(__GNUC__, < 3)
+  Function tmp(function);
+  tmp();
+#else
+  using namespace asio;
+  asio_handler_invoke(function, boost::addressof(context));
+#endif
+}
+
+} // namespace asio_handler_invoke_helpers
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP

+ 324 - 0
ext/asio/asio/detail/hash_map.hpp

@@ -0,0 +1,324 @@
+//
+// hash_map.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_HASH_MAP_HPP
+#define ASIO_DETAIL_HASH_MAP_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 <cassert>
+#include <list>
+#include <utility>
+#include <boost/functional/hash.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/socket_types.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename T>
+inline std::size_t calculate_hash_value(const T& t)
+{
+  return boost::hash_value(t);
+}
+
+#if defined(_WIN64)
+inline std::size_t calculate_hash_value(SOCKET s)
+{
+  return static_cast<std::size_t>(s);
+}
+#endif // defined(_WIN64)
+
+// Note: assumes K and V are POD types.
+template <typename K, typename V>
+class hash_map
+  : private noncopyable
+{
+public:
+  // The type of a value in the map.
+  typedef std::pair<K, V> value_type;
+
+  // The type of a non-const iterator over the hash map.
+  typedef typename std::list<value_type>::iterator iterator;
+
+  // The type of a const iterator over the hash map.
+  typedef typename std::list<value_type>::const_iterator const_iterator;
+
+  // Constructor.
+  hash_map()
+    : size_(0),
+      buckets_(0),
+      num_buckets_(0)
+  {
+  }
+
+  // Destructor.
+  ~hash_map()
+  {
+    delete[] buckets_;
+  }
+
+  // Get an iterator for the beginning of the map.
+  iterator begin()
+  {
+    return values_.begin();
+  }
+
+  // Get an iterator for the beginning of the map.
+  const_iterator begin() const
+  {
+    return values_.begin();
+  }
+
+  // Get an iterator for the end of the map.
+  iterator end()
+  {
+    return values_.end();
+  }
+
+  // Get an iterator for the end of the map.
+  const_iterator end() const
+  {
+    return values_.end();
+  }
+
+  // Check whether the map is empty.
+  bool empty() const
+  {
+    return values_.empty();
+  }
+
+  // Find an entry in the map.
+  iterator find(const K& k)
+  {
+    if (num_buckets_)
+    {
+      size_t bucket = calculate_hash_value(k) % num_buckets_;
+      iterator it = buckets_[bucket].first;
+      if (it == values_.end())
+        return values_.end();
+      iterator end = buckets_[bucket].last;
+      ++end;
+      while (it != end)
+      {
+        if (it->first == k)
+          return it;
+        ++it;
+      }
+    }
+    return values_.end();
+  }
+
+  // Find an entry in the map.
+  const_iterator find(const K& k) const
+  {
+    if (num_buckets_)
+    {
+      size_t bucket = calculate_hash_value(k) % num_buckets_;
+      const_iterator it = buckets_[bucket].first;
+      if (it == values_.end())
+        return it;
+      const_iterator end = buckets_[bucket].last;
+      ++end;
+      while (it != end)
+      {
+        if (it->first == k)
+          return it;
+        ++it;
+      }
+    }
+    return values_.end();
+  }
+
+  // Insert a new entry into the map.
+  std::pair<iterator, bool> insert(const value_type& v)
+  {
+    if (size_ + 1 >= num_buckets_)
+      rehash(hash_size(size_ + 1));
+    size_t bucket = calculate_hash_value(v.first) % num_buckets_;
+    iterator it = buckets_[bucket].first;
+    if (it == values_.end())
+    {
+      buckets_[bucket].first = buckets_[bucket].last =
+        values_insert(values_.end(), v);
+      ++size_;
+      return std::pair<iterator, bool>(buckets_[bucket].last, true);
+    }
+    iterator end = buckets_[bucket].last;
+    ++end;
+    while (it != end)
+    {
+      if (it->first == v.first)
+        return std::pair<iterator, bool>(it, false);
+      ++it;
+    }
+    buckets_[bucket].last = values_insert(end, v);
+    ++size_;
+    return std::pair<iterator, bool>(buckets_[bucket].last, true);
+  }
+
+  // Erase an entry from the map.
+  void erase(iterator it)
+  {
+    assert(it != values_.end());
+
+    size_t bucket = calculate_hash_value(it->first) % num_buckets_;
+    bool is_first = (it == buckets_[bucket].first);
+    bool is_last = (it == buckets_[bucket].last);
+    if (is_first && is_last)
+      buckets_[bucket].first = buckets_[bucket].last = values_.end();
+    else if (is_first)
+      ++buckets_[bucket].first;
+    else if (is_last)
+      --buckets_[bucket].last;
+
+    values_erase(it);
+    --size_;
+  }
+
+  // Erase a key from the map.
+  void erase(const K& k)
+  {
+    iterator it = find(k);
+    if (it != values_.end())
+      erase(it);
+  }
+
+  // Remove all entries from the map.
+  void clear()
+  {
+    // Clear the values.
+    values_.clear();
+    size_ = 0;
+
+    // Initialise all buckets to empty.
+    iterator end = values_.end();
+    for (size_t i = 0; i < num_buckets_; ++i)
+      buckets_[i].first = buckets_[i].last = end;
+  }
+
+private:
+  // Calculate the hash size for the specified number of elements.
+  static std::size_t hash_size(std::size_t num_elems)
+  {
+    static std::size_t sizes[] =
+    {
+#if defined(ASIO_HASH_MAP_BUCKETS)
+      ASIO_HASH_MAP_BUCKETS
+#else // ASIO_HASH_MAP_BUCKETS
+      3, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
+      49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
+      12582917, 25165843
+#endif // ASIO_HASH_MAP_BUCKETS
+    };
+    const std::size_t nth_size = sizeof(sizes) / sizeof(std::size_t) - 1;
+    for (std::size_t i = 0; i < nth_size; ++i)
+      if (num_elems < sizes[i])
+        return sizes[i];
+    return sizes[nth_size];
+  }
+
+  // Re-initialise the hash from the values already contained in the list.
+  void rehash(std::size_t num_buckets)
+  {
+    if (num_buckets == num_buckets_)
+      return;
+    num_buckets_ = num_buckets;
+
+    iterator end = values_.end();
+
+    // Update number of buckets and initialise all buckets to empty.
+    bucket_type* tmp = new bucket_type[num_buckets_];
+    delete[] buckets_;
+    buckets_ = tmp;
+    for (std::size_t i = 0; i < num_buckets_; ++i)
+      buckets_[i].first = buckets_[i].last = end;
+
+    // Put all values back into the hash.
+    iterator iter = values_.begin();
+    while (iter != end)
+    {
+      std::size_t bucket = calculate_hash_value(iter->first) % num_buckets_;
+      if (buckets_[bucket].last == end)
+      {
+        buckets_[bucket].first = buckets_[bucket].last = iter++;
+      }
+      else if (++buckets_[bucket].last == iter)
+      {
+        ++iter;
+      }
+      else
+      {
+        values_.splice(buckets_[bucket].last, values_, iter++);
+        --buckets_[bucket].last;
+      }
+    }
+  }
+
+  // Insert an element into the values list by splicing from the spares list,
+  // if a spare is available, and otherwise by inserting a new element.
+  iterator values_insert(iterator it, const value_type& v)
+  {
+    if (spares_.empty())
+    {
+      return values_.insert(it, v);
+    }
+    else
+    {
+      spares_.front() = v;
+      values_.splice(it, spares_, spares_.begin());
+      return --it;
+    }
+  }
+
+  // Erase an element from the values list by splicing it to the spares list.
+  void values_erase(iterator it)
+  {
+    *it = value_type();
+    spares_.splice(spares_.begin(), values_, it);
+  }
+
+  // The number of elements in the hash.
+  std::size_t size_;
+
+  // The list of all values in the hash map.
+  std::list<value_type> values_;
+
+  // The list of spare nodes waiting to be recycled. Assumes that POD types only
+  // are stored in the hash map.
+  std::list<value_type> spares_;
+
+  // The type for a bucket in the hash table.
+  struct bucket_type
+  {
+    iterator first;
+    iterator last;
+  };
+
+  // The buckets in the hash.
+  bucket_type* buckets_;
+
+  // The number of buckets in the hash.
+  std::size_t num_buckets_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_HASH_MAP_HPP

+ 137 - 0
ext/asio/asio/detail/io_control.hpp

@@ -0,0 +1,137 @@
+//
+// io_control.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_IO_CONTROL_HPP
+#define ASIO_DETAIL_IO_CONTROL_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 <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/socket_types.hpp"
+
+namespace asio {
+namespace detail {
+namespace io_control {
+
+// IO control command for non-blocking I/O.
+class non_blocking_io
+{
+public:
+  // Default constructor.
+  non_blocking_io()
+    : value_(0)
+  {
+  }
+
+  // Construct with a specific command value.
+  non_blocking_io(bool value)
+    : value_(value ? 1 : 0)
+  {
+  }
+
+  // Get the name of the IO control command.
+  int name() const
+  {
+    return FIONBIO;
+  }
+
+  // Set the value of the I/O control command.
+  void set(bool value)
+  {
+    value_ = value ? 1 : 0;
+  }
+
+  // Get the current value of the I/O control command.
+  bool get() const
+  {
+    return value_ != 0;
+  }
+
+  // Get the address of the command data.
+  detail::ioctl_arg_type* data()
+  {
+    return &value_;
+  }
+
+  // Get the address of the command data.
+  const detail::ioctl_arg_type* data() const
+  {
+    return &value_;
+  }
+
+private:
+  detail::ioctl_arg_type value_;
+};
+
+// I/O control command for getting number of bytes available.
+class bytes_readable
+{
+public:
+  // Default constructor.
+  bytes_readable()
+    : value_(0)
+  {
+  }
+
+  // Construct with a specific command value.
+  bytes_readable(std::size_t value)
+    : value_(static_cast<detail::ioctl_arg_type>(value))
+  {
+  }
+
+  // Get the name of the IO control command.
+  int name() const
+  {
+    return FIONREAD;
+  }
+
+  // Set the value of the I/O control command.
+  void set(std::size_t value)
+  {
+    value_ = static_cast<detail::ioctl_arg_type>(value);
+  }
+
+  // Get the current value of the I/O control command.
+  std::size_t get() const
+  {
+    return static_cast<std::size_t>(value_);
+  }
+
+  // Get the address of the command data.
+  detail::ioctl_arg_type* data()
+  {
+    return &value_;
+  }
+
+  // Get the address of the command data.
+  const detail::ioctl_arg_type* data() const
+  {
+    return &value_;
+  }
+
+private:
+  detail::ioctl_arg_type value_;
+};
+
+} // namespace io_control
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IO_CONTROL_HPP

+ 485 - 0
ext/asio/asio/detail/kqueue_reactor.hpp

@@ -0,0 +1,485 @@
+//
+// kqueue_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005 Stefan Arentz (stefan at soze 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_KQUEUE_REACTOR_HPP
+#define ASIO_DETAIL_KQUEUE_REACTOR_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/kqueue_reactor_fwd.hpp"
+
+#if defined(ASIO_HAS_KQUEUE)
+
+#include "asio/detail/push_options.hpp"
+#include <cstddef>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/hash_map.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/op_queue.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/select_interrupter.hpp"
+#include "asio/detail/service_base.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/timer_op.hpp"
+#include "asio/detail/timer_queue_base.hpp"
+#include "asio/detail/timer_queue_fwd.hpp"
+#include "asio/detail/timer_queue_set.hpp"
+
+// Older versions of Mac OS X may not define EV_OOBAND.
+#if !defined(EV_OOBAND)
+# define EV_OOBAND EV_FLAG1
+#endif // !defined(EV_OOBAND)
+
+namespace asio {
+namespace detail {
+
+class kqueue_reactor
+  : public asio::detail::service_base<kqueue_reactor>
+{
+public:
+  enum op_types { read_op = 0, write_op = 1,
+    connect_op = 1, except_op = 2, max_ops = 3 };
+
+  // Per-descriptor queues.
+  struct descriptor_state
+  {
+    descriptor_state() {}
+    descriptor_state(const descriptor_state&) {}
+    void operator=(const descriptor_state&) {}
+
+    mutex mutex_;
+    op_queue<reactor_op> op_queue_[max_ops];
+    bool shutdown_;
+  };
+
+  // Per-descriptor data.
+  typedef descriptor_state* per_descriptor_data;
+
+  // Constructor.
+  kqueue_reactor(asio::io_service& io_service)
+    : asio::detail::service_base<kqueue_reactor>(io_service),
+      io_service_(use_service<io_service_impl>(io_service)),
+      mutex_(),
+      kqueue_fd_(do_kqueue_create()),
+      interrupter_(),
+      shutdown_(false)
+  {
+    // The interrupter is put into a permanently readable state. Whenever we
+    // want to interrupt the blocked kevent call we register a one-shot read
+    // operation against the descriptor.
+    interrupter_.interrupt();
+  }
+
+  // Destructor.
+  ~kqueue_reactor()
+  {
+    close(kqueue_fd_);
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    mutex::scoped_lock lock(mutex_);
+    shutdown_ = true;
+    lock.unlock();
+
+    op_queue<operation> ops;
+
+    descriptor_map::iterator iter = registered_descriptors_.begin();
+    descriptor_map::iterator end = registered_descriptors_.end();
+    while (iter != end)
+    {
+      for (int i = 0; i < max_ops; ++i)
+        ops.push(iter->second.op_queue_[i]);
+      iter->second.shutdown_ = true;
+      ++iter;
+    }
+
+    timer_queues_.get_all_timers(ops);
+  }
+
+  // Initialise the task.
+  void init_task()
+  {
+    io_service_.init_task();
+  }
+
+  // Register a socket with the reactor. Returns 0 on success, system error
+  // code on failure.
+  int register_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data)
+  {
+    mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+    descriptor_map::iterator new_entry = registered_descriptors_.insert(
+          std::make_pair(descriptor, descriptor_state())).first;
+    descriptor_data = &new_entry->second;
+
+    descriptor_data->shutdown_ = false;
+
+    return 0;
+  }
+
+  // Start a new operation. The reactor operation will be performed when the
+  // given descriptor is flagged as ready, or an error has occurred.
+  void start_op(int op_type, socket_type descriptor,
+      per_descriptor_data& descriptor_data,
+      reactor_op* op, bool allow_speculative)
+  {
+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+    if (descriptor_data->shutdown_)
+      return;
+
+    bool first = descriptor_data->op_queue_[op_type].empty();
+    if (first)
+    {
+      if (allow_speculative)
+      {
+        if (op_type != read_op || descriptor_data->op_queue_[except_op].empty())
+        {
+          if (op->perform())
+          {
+            descriptor_lock.unlock();
+            io_service_.post_immediate_completion(op);
+            return;
+          }
+        }
+      }
+    }
+
+    descriptor_data->op_queue_[op_type].push(op);
+    io_service_.work_started();
+
+    if (first)
+    {
+      struct kevent event;
+      switch (op_type)
+      {
+      case read_op:
+        EV_SET(&event, descriptor, EVFILT_READ,
+            EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+        break;
+      case write_op:
+        EV_SET(&event, descriptor, EVFILT_WRITE,
+            EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+        break;
+      case except_op:
+        if (!descriptor_data->op_queue_[read_op].empty())
+          return; // Already registered for read events.
+        EV_SET(&event, descriptor, EVFILT_READ,
+            EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
+        break;
+      }
+
+      if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+      {
+        op->ec_ = asio::error_code(errno,
+            asio::error::get_system_category());
+        descriptor_data->op_queue_[op_type].pop();
+        io_service_.post_deferred_completion(op);
+      }
+    }
+  }
+
+  // Cancel all operations associated with the given descriptor. The
+  // handlers associated with the descriptor will be invoked with the
+  // operation_aborted error.
+  void cancel_ops(socket_type descriptor, per_descriptor_data& descriptor_data)
+  {
+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+
+  // Cancel any operations that are running against the descriptor and remove
+  // its registration from the reactor.
+  void close_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data)
+  {
+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
+
+    // Remove the descriptor from the set of known descriptors. The descriptor
+    // will be automatically removed from the kqueue set when it is closed.
+    descriptor_data->shutdown_ = true;
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_lock.unlock();
+
+    registered_descriptors_.erase(descriptor);
+
+    descriptors_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+
+  // Add a new timer queue to the reactor.
+  template <typename Time_Traits>
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    mutex::scoped_lock lock(mutex_);
+    timer_queues_.insert(&timer_queue);
+  }
+
+  // Remove a timer queue from the reactor.
+  template <typename Time_Traits>
+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    mutex::scoped_lock lock(mutex_);
+    timer_queues_.erase(&timer_queue);
+  }
+
+  // Schedule a new operation in the given timer queue to expire at the
+  // specified absolute time.
+  template <typename Time_Traits>
+  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+      const typename Time_Traits::time_type& time, timer_op* op, void* token)
+  {
+    mutex::scoped_lock lock(mutex_);
+    if (!shutdown_)
+    {
+      bool earliest = timer_queue.enqueue_timer(time, op, token);
+      io_service_.work_started();
+      if (earliest)
+        interrupt();
+    }
+  }
+
+  // Cancel the timer operations associated with the given token. Returns the
+  // number of operations that have been posted or dispatched.
+  template <typename Time_Traits>
+  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+  {
+    mutex::scoped_lock lock(mutex_);
+    op_queue<operation> ops;
+    std::size_t n = timer_queue.cancel_timer(token, ops);
+    lock.unlock();
+    io_service_.post_deferred_completions(ops);
+    return n;
+  }
+
+  // Run the kqueue loop.
+  void run(bool block, op_queue<operation>& ops)
+  {
+    mutex::scoped_lock lock(mutex_);
+
+    // Determine how long to block while waiting for events.
+    timespec timeout_buf = { 0, 0 };
+    timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
+
+    lock.unlock();
+
+    // Block on the kqueue descriptor.
+    struct kevent events[128];
+    int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);
+
+    // Dispatch the waiting events.
+    for (int i = 0; i < num_events; ++i)
+    {
+      int descriptor = events[i].ident;
+      void* ptr = events[i].udata;
+      if (ptr == &interrupter_)
+      {
+        // No need to reset the interrupter since we're leaving the descriptor
+        // in a ready-to-read state and relying on one-shot notifications.
+      }
+      else
+      {
+        descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
+        mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+        // Exception operations must be processed first to ensure that any
+        // out-of-band data is read before normal data.
+        static const int filter[max_ops] =
+          { EVFILT_READ, EVFILT_WRITE, EVFILT_READ };
+        for (int j = max_ops - 1; j >= 0; --j)
+        {
+          if (events[i].filter == filter[j])
+          {
+            if (j != except_op || events[i].flags & EV_OOBAND)
+            {
+              while (reactor_op* op = descriptor_data->op_queue_[j].front())
+              {
+                if (events[i].flags & EV_ERROR)
+                {
+                  op->ec_ = asio::error_code(events[i].data,
+                      asio::error::get_system_category());
+                  descriptor_data->op_queue_[j].pop();
+                  ops.push(op);
+                }
+                if (op->perform())
+                {
+                  descriptor_data->op_queue_[j].pop();
+                  ops.push(op);
+                }
+                else
+                  break;
+              }
+            }
+          }
+        }
+
+        // Renew registration for event notifications.
+        struct kevent event;
+        switch (events[i].filter)
+        {
+        case EVFILT_READ:
+          if (!descriptor_data->op_queue_[read_op].empty())
+            EV_SET(&event, descriptor, EVFILT_READ,
+                EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+          else if (!descriptor_data->op_queue_[except_op].empty())
+            EV_SET(&event, descriptor, EVFILT_READ,
+                EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
+          else
+            continue;
+        case EVFILT_WRITE:
+          if (!descriptor_data->op_queue_[write_op].empty())
+            EV_SET(&event, descriptor, EVFILT_WRITE,
+                EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+          else
+            continue;
+        default:
+          break;
+        }
+        if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+        {
+          asio::error_code error(errno,
+              asio::error::get_system_category());
+          for (int j = 0; j < max_ops; ++j)
+          {
+            while (reactor_op* op = descriptor_data->op_queue_[j].front())
+            {
+              op->ec_ = error;
+              descriptor_data->op_queue_[j].pop();
+              ops.push(op);
+            }
+          }
+        }
+      }
+    }
+
+    lock.lock();
+    timer_queues_.get_ready_timers(ops);
+  }
+
+  // Interrupt the kqueue loop.
+  void interrupt()
+  {
+    struct kevent event;
+    EV_SET(&event, interrupter_.read_descriptor(),
+        EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
+    ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
+  }
+
+private:
+  // Create the kqueue file descriptor. Throws an exception if the descriptor
+  // cannot be created.
+  static int do_kqueue_create()
+  {
+    int fd = kqueue();
+    if (fd == -1)
+    {
+      boost::throw_exception(
+          asio::system_error(
+            asio::error_code(errno,
+              asio::error::get_system_category()),
+            "kqueue"));
+    }
+    return fd;
+  }
+
+  // Get the timeout value for the kevent call.
+  timespec* get_timeout(timespec& ts)
+  {
+    // By default we will wait no longer than 5 minutes. This will ensure that
+    // any changes to the system clock are detected after no longer than this.
+    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+    ts.tv_sec = usec / 1000000;
+    ts.tv_nsec = (usec % 1000000) * 1000;
+    return &ts;
+  }
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_;
+
+  // Mutex to protect access to internal data.
+  mutex mutex_;
+
+  // The kqueue file descriptor.
+  int kqueue_fd_;
+
+  // The interrupter is used to break a blocking kevent call.
+  select_interrupter interrupter_;
+
+  // The timer queues.
+  timer_queue_set timer_queues_;
+
+  // Whether the service has been shut down.
+  bool shutdown_;
+
+  // Mutex to protect access to the registered descriptors.
+  mutex registered_descriptors_mutex_;
+
+  // Keep track of all registered descriptors. This code relies on the fact that
+  // the hash_map implementation pools deleted nodes, meaning that we can assume
+  // our descriptor_state pointer remains valid even after the entry is removed.
+  // Technically this is not true for C++98, as that standard says that spliced
+  // elements in a list are invalidated. However, C++0x fixes this shortcoming
+  // so we'll just assume that C++98 std::list implementations will do the right
+  // thing anyway.
+  typedef detail::hash_map<socket_type, descriptor_state> descriptor_map;
+  descriptor_map registered_descriptors_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(ASIO_HAS_KQUEUE)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_KQUEUE_REACTOR_HPP

+ 44 - 0
ext/asio/asio/detail/kqueue_reactor_fwd.hpp

@@ -0,0 +1,44 @@
+//
+// kqueue_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005 Stefan Arentz (stefan at soze 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_KQUEUE_REACTOR_FWD_HPP
+#define ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+#if !defined(ASIO_DISABLE_KQUEUE)
+
+#if (defined(__MACH__) && defined(__APPLE__)) \
+  || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+
+// Define this to indicate that kqueue is supported on the target platform.
+#define ASIO_HAS_KQUEUE 1
+
+namespace asio {
+namespace detail {
+
+class kqueue_reactor;
+
+} // namespace detail
+} // namespace asio
+
+#endif // (defined(__MACH__) && defined(__APPLE__))
+       // || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+
+#endif // !defined(ASIO_DISABLE_KQUEUE)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP

+ 59 - 0
ext/asio/asio/detail/local_free_on_block_exit.hpp

@@ -0,0 +1,59 @@
+//
+// local_free_on_block_exit.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_LOCAL_FREE_ON_BLOCK_EXIT_HPP
+#define ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/socket_types.hpp"
+
+namespace asio {
+namespace detail {
+
+class local_free_on_block_exit
+  : private noncopyable
+{
+public:
+  // Constructor blocks all signals for the calling thread.
+  explicit local_free_on_block_exit(void* p)
+    : p_(p)
+  {
+  }
+
+  // Destructor restores the previous signal mask.
+  ~local_free_on_block_exit()
+  {
+    ::LocalFree(p_);
+  }
+
+private:
+  void* p_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP

+ 57 - 0
ext/asio/asio/detail/macos_fenced_block.hpp

@@ -0,0 +1,57 @@
+//
+// macos_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_MACOS_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_MACOS_FENCED_BLOCK_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#include "asio/detail/push_options.hpp"
+#include <libkern/OSAtomic.h>
+#include "asio/detail/pop_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class macos_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  macos_fenced_block()
+  {
+    OSMemoryBarrier();
+  }
+
+  // Destructor.
+  ~macos_fenced_block()
+  {
+    OSMemoryBarrier();
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(__MACH__) && defined(__APPLE__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP

+ 50 - 0
ext/asio/asio/detail/mutex.hpp

@@ -0,0 +1,50 @@
+//
+// mutex.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_MUTEX_HPP
+#define ASIO_DETAIL_MUTEX_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+# include "asio/detail/null_mutex.hpp"
+#elif defined(BOOST_WINDOWS)
+# include "asio/detail/win_mutex.hpp"
+#elif defined(BOOST_HAS_PTHREADS)
+# include "asio/detail/posix_mutex.hpp"
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+typedef null_mutex mutex;
+#elif defined(BOOST_WINDOWS)
+typedef win_mutex mutex;
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_mutex mutex;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_MUTEX_HPP

+ 55 - 0
ext/asio/asio/detail/noncopyable.hpp

@@ -0,0 +1,55 @@
+//
+// noncopyable.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NONCOPYABLE_HPP
+#define ASIO_DETAIL_NONCOPYABLE_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/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/detail/workaround.hpp>
+#include "asio/detail/pop_options.hpp"
+
+namespace asio {
+namespace detail {
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+// Redefine the noncopyable class for Borland C++ since that compiler does not
+// apply the empty base optimisation unless the base class contains a dummy
+// char data member.
+class noncopyable
+{
+protected:
+  noncopyable() {}
+  ~noncopyable() {}
+private:
+  noncopyable(const noncopyable&);
+  const noncopyable& operator=(const noncopyable&);
+  char dummy_;
+};
+#else
+using boost::noncopyable;
+#endif
+
+} // namespace detail
+
+using asio::detail::noncopyable;
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NONCOPYABLE_HPP

+ 77 - 0
ext/asio/asio/detail/null_buffers_op.hpp

@@ -0,0 +1,77 @@
+//
+// null_buffers_op.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NULL_BUFFERS_OP_HPP
+#define ASIO_DETAIL_NULL_BUFFERS_OP_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/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class null_buffers_op : public reactor_op
+{
+public:
+  null_buffers_op(Handler handler)
+    : reactor_op(&null_buffers_op::do_perform, &null_buffers_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static bool do_perform(reactor_op*)
+  {
+    return true;
+  }
+
+  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.
+    null_buffers_op* o(static_cast<null_buffers_op*>(base));
+    typedef handler_alloc_traits<Handler, null_buffers_op> alloc_traits;
+    handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      // 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_);
+      ptr.reset();
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NULL_BUFFERS_OP_HPP

+ 77 - 0
ext/asio/asio/detail/null_event.hpp

@@ -0,0 +1,77 @@
+//
+// null_event.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NULL_EVENT_HPP
+#define ASIO_DETAIL_NULL_EVENT_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+class null_event
+  : private noncopyable
+{
+public:
+  // Constructor.
+  null_event()
+  {
+  }
+
+  // Destructor.
+  ~null_event()
+  {
+  }
+
+  // Signal the event.
+  template <typename Lock>
+  void signal(Lock&)
+  {
+  }
+
+  // Signal the event and unlock the mutex.
+  template <typename Lock>
+  void signal_and_unlock(Lock&)
+  {
+  }
+
+  // Reset the event.
+  template <typename Lock>
+  void clear(Lock&)
+  {
+  }
+
+  // Wait for the event to become signalled.
+  template <typename Lock>
+  void wait(Lock&)
+  {
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NULL_EVENT_HPP

+ 43 - 0
ext/asio/asio/detail/null_fenced_block.hpp

@@ -0,0 +1,43 @@
+//
+// null_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NULL_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_NULL_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class null_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  null_fenced_block()
+  {
+  }
+
+  // Destructor.
+  ~null_fenced_block()
+  {
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NULL_FENCED_BLOCK_HPP

+ 66 - 0
ext/asio/asio/detail/null_mutex.hpp

@@ -0,0 +1,66 @@
+//
+// null_mutex.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NULL_MUTEX_HPP
+#define ASIO_DETAIL_NULL_MUTEX_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/scoped_lock.hpp"
+
+namespace asio {
+namespace detail {
+
+class null_mutex
+  : private noncopyable
+{
+public:
+  typedef asio::detail::scoped_lock<null_mutex> scoped_lock;
+
+  // Constructor.
+  null_mutex()
+  {
+  }
+
+  // Destructor.
+  ~null_mutex()
+  {
+  }
+
+  // Lock the mutex.
+  void lock()
+  {
+  }
+
+  // Unlock the mutex.
+  void unlock()
+  {
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NULL_MUTEX_HPP

+ 63 - 0
ext/asio/asio/detail/null_signal_blocker.hpp

@@ -0,0 +1,63 @@
+//
+// null_signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NULL_SIGNAL_BLOCKER_HPP
+#define ASIO_DETAIL_NULL_SIGNAL_BLOCKER_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+class null_signal_blocker
+  : private noncopyable
+{
+public:
+  // Constructor blocks all signals for the calling thread.
+  null_signal_blocker()
+  {
+  }
+
+  // Destructor restores the previous signal mask.
+  ~null_signal_blocker()
+  {
+  }
+
+  // Block all signals for the calling thread.
+  void block()
+  {
+  }
+
+  // Restore the previous signal mask.
+  void unblock()
+  {
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP

+ 68 - 0
ext/asio/asio/detail/null_thread.hpp

@@ -0,0 +1,68 @@
+//
+// null_thread.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NULL_THREAD_HPP
+#define ASIO_DETAIL_NULL_THREAD_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/push_options.hpp"
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+class null_thread
+  : private noncopyable
+{
+public:
+  // Constructor.
+  template <typename Function>
+  null_thread(Function f)
+  {
+    asio::system_error e(
+        asio::error::operation_not_supported, "thread");
+    boost::throw_exception(e);
+  }
+
+  // Destructor.
+  ~null_thread()
+  {
+  }
+
+  // Wait for the thread to exit.
+  void join()
+  {
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NULL_THREAD_HPP

+ 70 - 0
ext/asio/asio/detail/null_tss_ptr.hpp

@@ -0,0 +1,70 @@
+//
+// null_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_NULL_TSS_PTR_HPP
+#define ASIO_DETAIL_NULL_TSS_PTR_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename T>
+class null_tss_ptr
+  : private noncopyable
+{
+public:
+  // Constructor.
+  null_tss_ptr()
+    : value_(0)
+  {
+  }
+
+  // Destructor.
+  ~null_tss_ptr()
+  {
+  }
+
+  // Get the value.
+  operator T*() const
+  {
+    return value_;
+  }
+
+  // Set the value.
+  void operator=(T* value)
+  {
+    value_ = value;
+  }
+
+private:
+  T* value_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_NULL_TSS_PTR_HPP

+ 340 - 0
ext/asio/asio/detail/old_win_sdk_compat.hpp

@@ -0,0 +1,340 @@
+//
+// old_win_sdk_compat.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_OLD_WIN_SDK_COMPAT_HPP
+#define ASIO_DETAIL_OLD_WIN_SDK_COMPAT_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Guess whether we are building against on old Platform SDK.
+#if !defined(IN6ADDR_ANY_INIT)
+#define ASIO_HAS_OLD_WIN_SDK 1
+#endif // !defined(IN6ADDR_ANY_INIT)
+
+#if defined(ASIO_HAS_OLD_WIN_SDK)
+
+// Emulation of types that are missing from old Platform SDKs.
+//
+// N.B. this emulation is also used if building for a Windows 2000 target with
+// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support
+// in that case.
+
+namespace asio {
+namespace detail {
+
+enum
+{
+  sockaddr_storage_maxsize = 128, // Maximum size.
+  sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment.
+  sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)),
+  sockaddr_storage_pad2size = (sockaddr_storage_maxsize -
+      (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize))
+};
+
+struct sockaddr_storage_emulation
+{
+  short ss_family;
+  char __ss_pad1[sockaddr_storage_pad1size];
+  __int64 __ss_align;
+  char __ss_pad2[sockaddr_storage_pad2size];
+};
+
+struct in6_addr_emulation
+{
+  union
+  {
+    u_char Byte[16];
+    u_short Word[8];
+  } u;
+};
+
+#if !defined(s6_addr)
+# define _S6_un u
+# define _S6_u8 Byte
+# define s6_addr _S6_un._S6_u8
+#endif // !defined(s6_addr)
+
+struct sockaddr_in6_emulation
+{
+  short sin6_family;
+  u_short sin6_port;
+  u_long sin6_flowinfo;
+  in6_addr_emulation sin6_addr;
+  u_long sin6_scope_id;
+};
+
+struct ipv6_mreq_emulation
+{
+  in6_addr_emulation ipv6mr_multiaddr;
+  unsigned int ipv6mr_interface;
+};
+
+#if !defined(IN6ADDR_ANY_INIT)
+# define IN6ADDR_ANY_INIT { 0 }
+#endif
+
+#if !defined(IN6ADDR_LOOPBACK_INIT)
+# define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
+#endif
+
+struct addrinfo_emulation
+{
+  int ai_flags;
+  int ai_family;
+  int ai_socktype;
+  int ai_protocol;
+  size_t ai_addrlen;
+  char* ai_canonname;
+  sockaddr* ai_addr;
+  addrinfo_emulation* ai_next;
+};
+
+#if !defined(AI_PASSIVE)
+# define AI_PASSIVE 0x1
+#endif
+
+#if !defined(AI_CANONNAME)
+# define AI_CANONNAME 0x2
+#endif
+
+#if !defined(AI_NUMERICHOST)
+# define AI_NUMERICHOST 0x4
+#endif
+
+#if !defined(EAI_AGAIN)
+# define EAI_AGAIN WSATRY_AGAIN
+#endif
+
+#if !defined(EAI_BADFLAGS)
+# define EAI_BADFLAGS WSAEINVAL
+#endif
+
+#if !defined(EAI_FAIL)
+# define EAI_FAIL WSANO_RECOVERY
+#endif
+
+#if !defined(EAI_FAMILY)
+# define EAI_FAMILY WSAEAFNOSUPPORT
+#endif
+
+#if !defined(EAI_MEMORY)
+# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
+#endif
+
+#if !defined(EAI_NODATA)
+# define EAI_NODATA WSANO_DATA
+#endif
+
+#if !defined(EAI_NONAME)
+# define EAI_NONAME WSAHOST_NOT_FOUND
+#endif
+
+#if !defined(EAI_SERVICE)
+# define EAI_SERVICE WSATYPE_NOT_FOUND
+#endif
+
+#if !defined(EAI_SOCKTYPE)
+# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
+#endif
+
+#if !defined(NI_NOFQDN)
+# define NI_NOFQDN 0x01
+#endif
+
+#if !defined(NI_NUMERICHOST)
+# define NI_NUMERICHOST 0x02
+#endif
+
+#if !defined(NI_NAMEREQD)
+# define NI_NAMEREQD 0x04
+#endif
+
+#if !defined(NI_NUMERICSERV)
+# define NI_NUMERICSERV 0x08
+#endif
+
+#if !defined(NI_DGRAM)
+# define NI_DGRAM 0x10
+#endif
+
+#if !defined(IPPROTO_IPV6)
+# define IPPROTO_IPV6 41
+#endif
+
+#if !defined(IPV6_UNICAST_HOPS)
+# define IPV6_UNICAST_HOPS 4
+#endif
+
+#if !defined(IPV6_MULTICAST_IF)
+# define IPV6_MULTICAST_IF 9
+#endif
+
+#if !defined(IPV6_MULTICAST_HOPS)
+# define IPV6_MULTICAST_HOPS 10
+#endif
+
+#if !defined(IPV6_MULTICAST_LOOP)
+# define IPV6_MULTICAST_LOOP 11
+#endif
+
+#if !defined(IPV6_JOIN_GROUP)
+# define IPV6_JOIN_GROUP 12
+#endif
+
+#if !defined(IPV6_LEAVE_GROUP)
+# define IPV6_LEAVE_GROUP 13
+#endif
+
+inline int IN6_IS_ADDR_UNSPECIFIED(const in6_addr_emulation* a)
+{
+  return ((a->s6_addr[0] == 0)
+      && (a->s6_addr[1] == 0)
+      && (a->s6_addr[2] == 0)
+      && (a->s6_addr[3] == 0)
+      && (a->s6_addr[4] == 0)
+      && (a->s6_addr[5] == 0)
+      && (a->s6_addr[6] == 0)
+      && (a->s6_addr[7] == 0)
+      && (a->s6_addr[8] == 0)
+      && (a->s6_addr[9] == 0)
+      && (a->s6_addr[10] == 0)
+      && (a->s6_addr[11] == 0)
+      && (a->s6_addr[12] == 0)
+      && (a->s6_addr[13] == 0)
+      && (a->s6_addr[14] == 0)
+      && (a->s6_addr[15] == 0));
+}
+
+inline int IN6_IS_ADDR_LOOPBACK(const in6_addr_emulation* a)
+{
+  return ((a->s6_addr[0] == 0)
+      && (a->s6_addr[1] == 0)
+      && (a->s6_addr[2] == 0)
+      && (a->s6_addr[3] == 0)
+      && (a->s6_addr[4] == 0)
+      && (a->s6_addr[5] == 0)
+      && (a->s6_addr[6] == 0)
+      && (a->s6_addr[7] == 0)
+      && (a->s6_addr[8] == 0)
+      && (a->s6_addr[9] == 0)
+      && (a->s6_addr[10] == 0)
+      && (a->s6_addr[11] == 0)
+      && (a->s6_addr[12] == 0)
+      && (a->s6_addr[13] == 0)
+      && (a->s6_addr[14] == 0)
+      && (a->s6_addr[15] == 1));
+}
+
+inline int IN6_IS_ADDR_MULTICAST(const in6_addr_emulation* a)
+{
+  return (a->s6_addr[0] == 0xff);
+}
+
+inline int IN6_IS_ADDR_LINKLOCAL(const in6_addr_emulation* a)
+{
+  return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80));
+}
+
+inline int IN6_IS_ADDR_SITELOCAL(const in6_addr_emulation* a)
+{
+  return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0xc0));
+}
+
+inline int IN6_IS_ADDR_V4MAPPED(const in6_addr_emulation* a)
+{
+  return ((a->s6_addr[0] == 0)
+      && (a->s6_addr[1] == 0)
+      && (a->s6_addr[2] == 0)
+      && (a->s6_addr[3] == 0)
+      && (a->s6_addr[4] == 0)
+      && (a->s6_addr[5] == 0)
+      && (a->s6_addr[6] == 0)
+      && (a->s6_addr[7] == 0)
+      && (a->s6_addr[8] == 0)
+      && (a->s6_addr[9] == 0)
+      && (a->s6_addr[10] == 0xff)
+      && (a->s6_addr[11] == 0xff));
+}
+
+inline int IN6_IS_ADDR_V4COMPAT(const in6_addr_emulation* a)
+{
+  return ((a->s6_addr[0] == 0)
+      && (a->s6_addr[1] == 0)
+      && (a->s6_addr[2] == 0)
+      && (a->s6_addr[3] == 0)
+      && (a->s6_addr[4] == 0)
+      && (a->s6_addr[5] == 0)
+      && (a->s6_addr[6] == 0)
+      && (a->s6_addr[7] == 0)
+      && (a->s6_addr[8] == 0)
+      && (a->s6_addr[9] == 0)
+      && (a->s6_addr[10] == 0xff)
+      && (a->s6_addr[11] == 0xff)
+      && !((a->s6_addr[12] == 0)
+        && (a->s6_addr[13] == 0)
+        && (a->s6_addr[14] == 0)
+        && ((a->s6_addr[15] == 0) || (a->s6_addr[15] == 1))));
+}
+
+inline int IN6_IS_ADDR_MC_NODELOCAL(const in6_addr_emulation* a)
+{
+  return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 1);
+}
+
+inline int IN6_IS_ADDR_MC_LINKLOCAL(const in6_addr_emulation* a)
+{
+  return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 2);
+}
+
+inline int IN6_IS_ADDR_MC_SITELOCAL(const in6_addr_emulation* a)
+{
+  return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 5);
+}
+
+inline int IN6_IS_ADDR_MC_ORGLOCAL(const in6_addr_emulation* a)
+{
+  return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 8);
+}
+
+inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a)
+{
+  return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 0xe);
+}
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(ASIO_HAS_OLD_WIN_SDK)
+
+// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY.
+#if !defined(IPV6_V6ONLY)
+# define IPV6_V6ONLY 27
+#endif
+
+// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6.
+#if !defined(IPPROTO_ICMPV6)
+# define IPPROTO_ICMPV6 58
+#endif
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP

+ 156 - 0
ext/asio/asio/detail/op_queue.hpp

@@ -0,0 +1,156 @@
+//
+// op_queue.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_OP_QUEUE_HPP
+#define ASIO_DETAIL_OP_QUEUE_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/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Operation>
+class op_queue;
+
+class op_queue_access
+{
+public:
+  template <typename Operation>
+  static Operation* next(Operation* o)
+  {
+    return static_cast<Operation*>(o->next_);
+  }
+
+  template <typename Operation1, typename Operation2>
+  static void next(Operation1*& o1, Operation2* o2)
+  {
+    o1->next_ = o2;
+  }
+
+  template <typename Operation>
+  static void destroy(Operation* o)
+  {
+    o->destroy();
+  }
+
+  template <typename Operation>
+  static Operation*& front(op_queue<Operation>& q)
+  {
+    return q.front_;
+  }
+
+  template <typename Operation>
+  static Operation*& back(op_queue<Operation>& q)
+  {
+    return q.back_;
+  }
+};
+
+template <typename Operation>
+class op_queue
+  : private noncopyable
+{
+public:
+  // Constructor.
+  op_queue()
+    : front_(0),
+      back_(0)
+  {
+  }
+
+  // Destructor destroys all operations.
+  ~op_queue()
+  {
+    while (Operation* op = front_)
+    {
+      pop();
+      op_queue_access::destroy(op);
+    }
+  }
+
+  // Get the operation at the front of the queue.
+  Operation* front()
+  {
+    return front_;
+  }
+
+  // Pop an operation from the front of the queue.
+  void pop()
+  {
+    if (front_)
+    {
+      Operation* tmp = front_;
+      front_ = op_queue_access::next(front_);
+      if (front_ == 0)
+        back_ = 0;
+      op_queue_access::next(tmp, static_cast<Operation*>(0));
+    }
+  }
+
+  // Push an operation on to the back of the queue.
+  void push(Operation* h)
+  {
+    op_queue_access::next(h, static_cast<Operation*>(0));
+    if (back_)
+    {
+      op_queue_access::next(back_, h);
+      back_ = h;
+    }
+    else
+    {
+      front_ = back_ = h;
+    }
+  }
+
+  // Push all operations from another queue on to the back of the queue. The
+  // source queue may contain operations of a derived type.
+  template <typename OtherOperation>
+  void push(op_queue<OtherOperation>& q)
+  {
+    if (Operation* other_front = op_queue_access::front(q))
+    {
+      if (back_)
+        op_queue_access::next(back_, other_front);
+      else
+        front_ = other_front;
+      back_ = op_queue_access::back(q);
+      op_queue_access::front(q) = 0;
+      op_queue_access::back(q) = 0;
+    }
+  }
+
+  // Whether the queue is empty.
+  bool empty() const
+  {
+    return front_ == 0;
+  }
+
+private:
+  friend class op_queue_access;
+
+  // The front of the queue.
+  Operation* front_;
+
+  // The back of the queue.
+  Operation* back_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_OP_QUEUE_HPP

+ 43 - 0
ext/asio/asio/detail/operation.hpp

@@ -0,0 +1,43 @@
+//
+// operation.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_OPERATION_HPP
+#define ASIO_DETAIL_OPERATION_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/win_iocp_io_service_fwd.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_operation.hpp"
+#else
+# include "asio/detail/reactor_fwd.hpp"
+# include "asio/detail/task_io_service_operation.hpp"
+#endif
+
+namespace asio {
+namespace detail {
+
+#if defined(ASIO_HAS_IOCP)
+typedef win_iocp_operation operation;
+#else
+typedef task_io_service_operation<reactor> operation;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_OPERATION_HPP

+ 120 - 0
ext/asio/asio/detail/pipe_select_interrupter.hpp

@@ -0,0 +1,120 @@
+//
+// pipe_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_PIPE_SELECT_INTERRUPTER_HPP
+#define ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_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/config.hpp>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/push_options.hpp"
+#include <fcntl.h>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/socket_types.hpp"
+
+namespace asio {
+namespace detail {
+
+class pipe_select_interrupter
+{
+public:
+  // Constructor.
+  pipe_select_interrupter()
+  {
+    int pipe_fds[2];
+    if (pipe(pipe_fds) == 0)
+    {
+      read_descriptor_ = pipe_fds[0];
+      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+      write_descriptor_ = pipe_fds[1];
+      ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+    }
+    else
+    {
+      asio::error_code ec(errno,
+          asio::error::get_system_category());
+      asio::system_error e(ec, "pipe_select_interrupter");
+      boost::throw_exception(e);
+    }
+  }
+
+  // Destructor.
+  ~pipe_select_interrupter()
+  {
+    if (read_descriptor_ != -1)
+      ::close(read_descriptor_);
+    if (write_descriptor_ != -1)
+      ::close(write_descriptor_);
+  }
+
+  // Interrupt the select call.
+  void interrupt()
+  {
+    char byte = 0;
+    int result = ::write(write_descriptor_, &byte, 1);
+    (void)result;
+  }
+
+  // Reset the select interrupt. Returns true if the call was interrupted.
+  bool reset()
+  {
+    for (;;)
+    {
+      char data[1024];
+      int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      if (bytes_read < 0 && errno == EINTR)
+        continue;
+      bool was_interrupted = (bytes_read > 0);
+      while (bytes_read == sizeof(data))
+        bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      return was_interrupted;
+    }
+  }
+
+  // Get the read descriptor to be passed to select.
+  int read_descriptor() const
+  {
+    return read_descriptor_;
+  }
+
+private:
+  // The read end of a connection used to interrupt the select call. This file
+  // descriptor is passed to select such that when it is time to stop, a single
+  // byte will be written on the other end of the connection and this
+  // descriptor will become readable.
+  int read_descriptor_;
+
+  // The write end of a connection used to interrupt the select call. A single
+  // byte may be written to this to wake up the select which is waiting for the
+  // other end to become readable.
+  int write_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP

+ 88 - 0
ext/asio/asio/detail/pop_options.hpp

@@ -0,0 +1,88 @@
+//
+// pop_options.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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)
+//
+
+// No header guard
+
+#if defined(__COMO__)
+
+// Comeau C++
+
+#elif defined(__DMC__)
+
+// Digital Mars C++
+
+#elif defined(__INTEL_COMPILER) || defined(__ICL) \
+  || defined(__ICC) || defined(__ECC)
+
+// Intel C++
+
+#elif defined(__GNUC__)
+
+// GNU C++
+
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+#  pragma pack (pop)
+# endif
+
+#elif defined(__KCC)
+
+// Kai C++
+
+#elif defined(__sgi)
+
+// SGI MIPSpro C++
+
+#elif defined(__DECCXX)
+
+// Compaq Tru64 Unix cxx
+
+#elif defined(__ghs)
+
+// Greenhills C++
+
+#elif defined(__BORLANDC__)
+
+// Borland C++
+
+# pragma option pop
+# pragma nopushoptwarn
+# pragma nopackwarning
+
+#elif defined(__MWERKS__)
+
+// Metrowerks CodeWarrior
+
+#elif defined(__SUNPRO_CC)
+
+// Sun Workshop Compiler C++
+
+#elif defined(__HP_aCC)
+
+// HP aCC
+
+#elif defined(__MRC__) || defined(__SC__)
+
+// MPW MrCpp or SCpp
+
+#elif defined(__IBMCPP__)
+
+// IBM Visual Age
+
+#elif defined(_MSC_VER)
+
+// Microsoft Visual C++
+//
+// Must remain the last #elif since some other vendors (Metrowerks, for example)
+// also #define _MSC_VER
+
+# pragma warning (pop)
+# pragma pack (pop)
+
+#endif

+ 114 - 0
ext/asio/asio/detail/posix_event.hpp

@@ -0,0 +1,114 @@
+//
+// posix_event.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_POSIX_EVENT_HPP
+#define ASIO_DETAIL_POSIX_EVENT_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/push_options.hpp"
+#include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+class posix_event
+  : private noncopyable
+{
+public:
+  // Constructor.
+  posix_event()
+    : signalled_(false)
+  {
+    int error = ::pthread_cond_init(&cond_, 0);
+    if (error != 0)
+    {
+      asio::system_error e(
+          asio::error_code(error,
+            asio::error::get_system_category()),
+          "event");
+      boost::throw_exception(e);
+    }
+  }
+
+  // Destructor.
+  ~posix_event()
+  {
+    ::pthread_cond_destroy(&cond_);
+  }
+
+  // Signal the event.
+  template <typename Lock>
+  void signal(Lock& lock)
+  {
+    BOOST_ASSERT(lock.locked());
+    (void)lock;
+    signalled_ = true;
+    ::pthread_cond_signal(&cond_); // Ignore EINVAL.
+  }
+
+  // Signal the event and unlock the mutex.
+  template <typename Lock>
+  void signal_and_unlock(Lock& lock)
+  {
+    BOOST_ASSERT(lock.locked());
+    signalled_ = true;
+    lock.unlock();
+    ::pthread_cond_signal(&cond_); // Ignore EINVAL.
+  }
+
+  // Reset the event.
+  template <typename Lock>
+  void clear(Lock& lock)
+  {
+    BOOST_ASSERT(lock.locked());
+    (void)lock;
+    signalled_ = false;
+  }
+
+  // Wait for the event to become signalled.
+  template <typename Lock>
+  void wait(Lock& lock)
+  {
+    BOOST_ASSERT(lock.locked());
+    while (!signalled_)
+      ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL.
+  }
+
+private:
+  ::pthread_cond_t cond_;
+  bool signalled_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_POSIX_EVENT_HPP

+ 81 - 0
ext/asio/asio/detail/posix_fd_set_adapter.hpp

@@ -0,0 +1,81 @@
+//
+// posix_fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_POSIX_FD_SET_ADAPTER_HPP
+#define ASIO_DETAIL_POSIX_FD_SET_ADAPTER_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 <cstring>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/socket_types.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace asio {
+namespace detail {
+
+// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.
+class posix_fd_set_adapter
+{
+public:
+  posix_fd_set_adapter()
+    : max_descriptor_(invalid_socket)
+  {
+    using namespace std; // Needed for memset on Solaris.
+    FD_ZERO(&fd_set_);
+  }
+
+  bool set(socket_type descriptor)
+  {
+    if (descriptor < (socket_type)FD_SETSIZE)
+    {
+      if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_)
+        max_descriptor_ = descriptor;
+      FD_SET(descriptor, &fd_set_);
+      return true;
+    }
+    return false;
+  }
+
+  bool is_set(socket_type descriptor) const
+  {
+    return FD_ISSET(descriptor, &fd_set_) != 0;
+  }
+
+  operator fd_set*()
+  {
+    return &fd_set_;
+  }
+
+  socket_type max_descriptor() const
+  {
+    return max_descriptor_;
+  }
+
+private:
+  mutable fd_set fd_set_;
+  socket_type max_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP

+ 91 - 0
ext/asio/asio/detail/posix_mutex.hpp

@@ -0,0 +1,91 @@
+//
+// posix_mutex.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_POSIX_MUTEX_HPP
+#define ASIO_DETAIL_POSIX_MUTEX_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/push_options.hpp"
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/scoped_lock.hpp"
+
+namespace asio {
+namespace detail {
+
+class posix_event;
+
+class posix_mutex
+  : private noncopyable
+{
+public:
+  typedef asio::detail::scoped_lock<posix_mutex> scoped_lock;
+
+  // Constructor.
+  posix_mutex()
+  {
+    int error = ::pthread_mutex_init(&mutex_, 0);
+    if (error != 0)
+    {
+      asio::system_error e(
+          asio::error_code(error,
+            asio::error::get_system_category()),
+          "mutex");
+      boost::throw_exception(e);
+    }
+  }
+
+  // Destructor.
+  ~posix_mutex()
+  {
+    ::pthread_mutex_destroy(&mutex_); // Ignore EBUSY.
+  }
+
+  // Lock the mutex.
+  void lock()
+  {
+    (void)::pthread_mutex_lock(&mutex_); // Ignore EINVAL.
+  }
+
+  // Unlock the mutex.
+  void unlock()
+  {
+    (void)::pthread_mutex_unlock(&mutex_); // Ignore EINVAL.
+  }
+
+private:
+  friend class posix_event;
+  ::pthread_mutex_t mutex_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_POSIX_MUTEX_HPP

+ 90 - 0
ext/asio/asio/detail/posix_signal_blocker.hpp

@@ -0,0 +1,90 @@
+//
+// posix_signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_POSIX_SIGNAL_BLOCKER_HPP
+#define ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/push_options.hpp"
+#include <csignal>
+#include <pthread.h>
+#include <signal.h>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+class posix_signal_blocker
+  : private noncopyable
+{
+public:
+  // Constructor blocks all signals for the calling thread.
+  posix_signal_blocker()
+    : blocked_(false)
+  {
+    sigset_t new_mask;
+    sigfillset(&new_mask);
+    blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);
+  }
+
+  // Destructor restores the previous signal mask.
+  ~posix_signal_blocker()
+  {
+    if (blocked_)
+      pthread_sigmask(SIG_SETMASK, &old_mask_, 0);
+  }
+
+  // Block all signals for the calling thread.
+  void block()
+  {
+    if (!blocked_)
+    {
+      sigset_t new_mask;
+      sigfillset(&new_mask);
+      blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);
+    }
+  }
+
+  // Restore the previous signal mask.
+  void unblock()
+  {
+    if (blocked_)
+      blocked_ = (pthread_sigmask(SIG_SETMASK, &old_mask_, 0) != 0);
+  }
+
+private:
+  // Have signals been blocked.
+  bool blocked_;
+
+  // The previous signal mask.
+  sigset_t old_mask_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP

+ 129 - 0
ext/asio/asio/detail/posix_thread.hpp

@@ -0,0 +1,129 @@
+//
+// posix_thread.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_POSIX_THREAD_HPP
+#define ASIO_DETAIL_POSIX_THREAD_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/push_options.hpp"
+#include <memory>
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+extern "C" void* asio_detail_posix_thread_function(void* arg);
+
+class posix_thread
+  : private noncopyable
+{
+public:
+  // Constructor.
+  template <typename Function>
+  posix_thread(Function f)
+    : joined_(false)
+  {
+    std::auto_ptr<func_base> arg(new func<Function>(f));
+    int error = ::pthread_create(&thread_, 0,
+          asio_detail_posix_thread_function, arg.get());
+    if (error != 0)
+    {
+      asio::system_error e(
+          asio::error_code(error,
+            asio::error::get_system_category()),
+          "thread");
+      boost::throw_exception(e);
+    }
+    arg.release();
+  }
+
+  // Destructor.
+  ~posix_thread()
+  {
+    if (!joined_)
+      ::pthread_detach(thread_);
+  }
+
+  // Wait for the thread to exit.
+  void join()
+  {
+    if (!joined_)
+    {
+      ::pthread_join(thread_, 0);
+      joined_ = true;
+    }
+  }
+
+private:
+  friend void* asio_detail_posix_thread_function(void* arg);
+
+  class func_base
+  {
+  public:
+    virtual ~func_base() {}
+    virtual void run() = 0;
+  };
+
+  template <typename Function>
+  class func
+    : public func_base
+  {
+  public:
+    func(Function f)
+      : f_(f)
+    {
+    }
+
+    virtual void run()
+    {
+      f_();
+    }
+
+  private:
+    Function f_;
+  };
+
+  ::pthread_t thread_;
+  bool joined_;
+};
+
+inline void* asio_detail_posix_thread_function(void* arg)
+{
+  std::auto_ptr<posix_thread::func_base> f(
+      static_cast<posix_thread::func_base*>(arg));
+  f->run();
+  return 0;
+}
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_POSIX_THREAD_HPP

+ 88 - 0
ext/asio/asio/detail/posix_tss_ptr.hpp

@@ -0,0 +1,88 @@
+//
+// posix_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_POSIX_TSS_PTR_HPP
+#define ASIO_DETAIL_POSIX_TSS_PTR_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/push_options.hpp"
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename T>
+class posix_tss_ptr
+  : private noncopyable
+{
+public:
+  // Constructor.
+  posix_tss_ptr()
+  {
+    int error = ::pthread_key_create(&tss_key_, 0);
+    if (error != 0)
+    {
+      asio::system_error e(
+          asio::error_code(error,
+            asio::error::get_system_category()),
+          "tss");
+      boost::throw_exception(e);
+    }
+  }
+
+  // Destructor.
+  ~posix_tss_ptr()
+  {
+    ::pthread_key_delete(tss_key_);
+  }
+
+  // Get the value.
+  operator T*() const
+  {
+    return static_cast<T*>(::pthread_getspecific(tss_key_));
+  }
+
+  // Set the value.
+  void operator=(T* value)
+  {
+    ::pthread_setspecific(tss_key_, value);
+  }
+
+private:
+  // Thread-specific storage to allow unlocked access to determine whether a
+  // thread is a member of the pool.
+  pthread_key_t tss_key_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP

+ 114 - 0
ext/asio/asio/detail/push_options.hpp

@@ -0,0 +1,114 @@
+//
+// push_options.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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)
+//
+
+// No header guard
+
+#if defined(__COMO__)
+
+// Comeau C++
+
+#elif defined(__DMC__)
+
+// Digital Mars C++
+
+#elif defined(__INTEL_COMPILER) || defined(__ICL) \
+  || defined(__ICC) || defined(__ECC)
+
+// Intel C++
+
+#elif defined(__GNUC__)
+
+// GNU C++
+
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+#  pragma pack (push, 8)
+# endif
+
+#elif defined(__KCC)
+
+// Kai C++
+
+#elif defined(__sgi)
+
+// SGI MIPSpro C++
+
+#elif defined(__DECCXX)
+
+// Compaq Tru64 Unix cxx
+
+#elif defined(__ghs)
+
+// Greenhills C++
+
+#elif defined(__BORLANDC__)
+
+// Borland C++
+
+# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi-
+# pragma nopushoptwarn
+# pragma nopackwarning
+# if !defined(__MT__)
+#  error Multithreaded RTL must be selected.
+# endif // !defined(__MT__)
+
+#elif defined(__MWERKS__)
+
+// Metrowerks CodeWarrior
+
+#elif defined(__SUNPRO_CC)
+
+// Sun Workshop Compiler C++
+
+#elif defined(__HP_aCC)
+
+// HP aCC
+
+#elif defined(__MRC__) || defined(__SC__)
+
+// MPW MrCpp or SCpp
+
+#elif defined(__IBMCPP__)
+
+// IBM Visual Age
+
+#elif defined(_MSC_VER)
+
+// Microsoft Visual C++
+//
+// Must remain the last #elif since some other vendors (Metrowerks, for example)
+// also #define _MSC_VER
+
+# pragma warning (disable:4103)
+# pragma warning (push)
+# pragma warning (disable:4127)
+# pragma warning (disable:4244)
+# pragma warning (disable:4355)
+# pragma warning (disable:4512)
+# pragma warning (disable:4675)
+# if defined(_M_IX86) && defined(_Wp64)
+// The /Wp64 option is broken. If you want to check 64 bit portability, use a
+// 64 bit compiler!
+#  pragma warning (disable:4311)
+#  pragma warning (disable:4312)
+# endif // defined(_M_IX86) && defined(_Wp64)
+# pragma pack (push, 8)
+// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler
+// has a tendency to incorrectly optimise away some calls to member template
+// functions, even though those functions contain code that should not be
+// optimised away! Therefore we will always disable this optimisation option
+// for the MSVC6 compiler.
+# if (_MSC_VER < 1300)
+#  pragma optimize ("g", off)
+# endif
+# if !defined(_MT)
+#  error Multithreaded RTL must be selected.
+# endif // !defined(_MT)
+
+#endif

+ 668 - 0
ext/asio/asio/detail/reactive_descriptor_service.hpp

@@ -0,0 +1,668 @@
+//
+// reactive_descriptor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_DESCRIPTOR_SERVICE_HPP
+#define ASIO_DETAIL_REACTIVE_DESCRIPTOR_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/buffer.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/null_buffers_op.hpp"
+#include "asio/detail/reactor.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace asio {
+namespace detail {
+
+class reactive_descriptor_service
+{
+public:
+  // The native type of a descriptor.
+  typedef int native_type;
+
+  // The implementation type of the descriptor.
+  class implementation_type
+    : private asio::detail::noncopyable
+  {
+  public:
+    // Default constructor.
+    implementation_type()
+      : descriptor_(-1),
+        flags_(0)
+    {
+    }
+
+  private:
+    // Only this service will have access to the internal values.
+    friend class reactive_descriptor_service;
+
+    // The native descriptor representation.
+    int descriptor_;
+
+    enum
+    {
+      // The user wants a non-blocking descriptor.
+      user_set_non_blocking = 1,
+
+      // The descriptor has been set non-blocking.
+      internal_non_blocking = 2,
+
+      // Helper "flag" used to determine whether the descriptor is non-blocking.
+      non_blocking = user_set_non_blocking | internal_non_blocking
+    };
+
+    // Flags indicating the current state of the descriptor.
+    unsigned char flags_;
+
+    // Per-descriptor data used by the reactor.
+    reactor::per_descriptor_data reactor_data_;
+  };
+
+  // The maximum number of buffers to support in a single operation.
+  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+
+  // Constructor.
+  reactive_descriptor_service(asio::io_service& io_service)
+    : io_service_impl_(asio::use_service<io_service_impl>(io_service)),
+      reactor_(asio::use_service<reactor>(io_service))
+  {
+    reactor_.init_task();
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+  }
+
+  // Construct a new descriptor implementation.
+  void construct(implementation_type& impl)
+  {
+    impl.descriptor_ = -1;
+    impl.flags_ = 0;
+  }
+
+  // Destroy a descriptor implementation.
+  void destroy(implementation_type& impl)
+  {
+    if (impl.descriptor_ != -1)
+    {
+      reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+      if (impl.flags_ & implementation_type::internal_non_blocking)
+      {
+        ioctl_arg_type non_blocking = 0;
+        asio::error_code ignored_ec;
+        descriptor_ops::ioctl(impl.descriptor_,
+            FIONBIO, &non_blocking, ignored_ec);
+        impl.flags_ &= ~implementation_type::internal_non_blocking;
+      }
+
+      asio::error_code ignored_ec;
+      descriptor_ops::close(impl.descriptor_, ignored_ec);
+
+      impl.descriptor_ = -1;
+    }
+  }
+
+  // Assign a native descriptor to a descriptor implementation.
+  asio::error_code assign(implementation_type& impl,
+      const native_type& native_descriptor, asio::error_code& ec)
+  {
+    if (is_open(impl))
+    {
+      ec = asio::error::already_open;
+      return ec;
+    }
+
+    if (int err = reactor_.register_descriptor(
+          native_descriptor, impl.reactor_data_))
+    {
+      ec = asio::error_code(err,
+          asio::error::get_system_category());
+      return ec;
+    }
+
+    impl.descriptor_ = native_descriptor;
+    impl.flags_ = 0;
+    ec = asio::error_code();
+    return ec;
+  }
+
+  // Determine whether the descriptor is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return impl.descriptor_ != -1;
+  }
+
+  // Destroy a descriptor implementation.
+  asio::error_code close(implementation_type& impl,
+      asio::error_code& ec)
+  {
+    if (is_open(impl))
+    {
+      reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+      if (impl.flags_ & implementation_type::internal_non_blocking)
+      {
+        ioctl_arg_type non_blocking = 0;
+        asio::error_code ignored_ec;
+        descriptor_ops::ioctl(impl.descriptor_,
+            FIONBIO, &non_blocking, ignored_ec);
+        impl.flags_ &= ~implementation_type::internal_non_blocking;
+      }
+
+      if (descriptor_ops::close(impl.descriptor_, ec) == -1)
+        return ec;
+
+      impl.descriptor_ = -1;
+    }
+
+    ec = asio::error_code();
+    return ec;
+  }
+
+  // Get the native descriptor representation.
+  native_type native(const implementation_type& impl) const
+  {
+    return impl.descriptor_;
+  }
+
+  // Cancel all operations associated with the descriptor.
+  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.descriptor_, impl.reactor_data_);
+    ec = asio::error_code();
+    return ec;
+  }
+
+  // Perform an IO control command on the descriptor.
+  template <typename IO_Control_Command>
+  asio::error_code io_control(implementation_type& impl,
+      IO_Control_Command& command, asio::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = asio::error::bad_descriptor;
+      return ec;
+    }
+
+    descriptor_ops::ioctl(impl.descriptor_, command.name(),
+        static_cast<ioctl_arg_type*>(command.data()), ec);
+
+    // When updating the non-blocking mode we always perform the ioctl syscall,
+    // even if the flags would otherwise indicate that the descriptor is
+    // already in the correct state. This ensures that the underlying
+    // descriptor is put into the state that has been requested by the user. If
+    // the ioctl syscall was successful then we need to update the flags to
+    // match.
+    if (!ec && command.name() == static_cast<int>(FIONBIO))
+    {
+      if (*static_cast<ioctl_arg_type*>(command.data()))
+      {
+        impl.flags_ |= implementation_type::user_set_non_blocking;
+      }
+      else
+      {
+        // Clearing the non-blocking mode always overrides any internally-set
+        // non-blocking flag. Any subsequent asynchronous operations will need
+        // to re-enable non-blocking I/O.
+        impl.flags_ &= ~(implementation_type::user_set_non_blocking
+            | implementation_type::internal_non_blocking);
+      }
+    }
+
+    return ec;
+  }
+
+  // Write some data to the descriptor.
+  template <typename ConstBufferSequence>
+  size_t write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, asio::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = asio::error::bad_descriptor;
+      return 0;
+    }
+
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(buffers);
+
+    // A request to read_some 0 bytes on a stream is a no-op.
+    if (bufs.all_empty())
+    {
+      ec = asio::error_code();
+      return 0;
+    }
+
+    // Send the data.
+    for (;;)
+    {
+      // Try to complete the operation without blocking.
+      int bytes_sent = descriptor_ops::gather_write(
+          impl.descriptor_, bufs.buffers(), bufs.count(), ec);
+
+      // Check if operation succeeded.
+      if (bytes_sent >= 0)
+        return bytes_sent;
+
+      // Operation failed.
+      if ((impl.flags_ & implementation_type::user_set_non_blocking)
+          || (ec != asio::error::would_block
+            && ec != asio::error::try_again))
+        return 0;
+
+      // Wait for descriptor to become ready.
+      if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0)
+        return 0;
+    }
+  }
+
+  // Wait until data can be written without blocking.
+  size_t write_some(implementation_type& impl,
+      const null_buffers&, asio::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = asio::error::bad_descriptor;
+      return 0;
+    }
+
+    // Wait for descriptor to become ready.
+    descriptor_ops::poll_write(impl.descriptor_, ec);
+
+    return 0;
+  }
+
+  template <typename ConstBufferSequence>
+  class write_op_base : public reactor_op
+  {
+  public:
+    write_op_base(int descriptor,
+        const ConstBufferSequence& buffers, func_type complete_func)
+      : reactor_op(&write_op_base::do_perform, complete_func),
+        descriptor_(descriptor),
+        buffers_(buffers)
+    {
+    }
+
+    static bool do_perform(reactor_op* base)
+    {
+      write_op_base* o(static_cast<write_op_base*>(base));
+
+      buffer_sequence_adapter<asio::const_buffer,
+          ConstBufferSequence> bufs(o->buffers_);
+
+      for (;;)
+      {
+        // Write the data.
+        asio::error_code ec;
+        int bytes = descriptor_ops::gather_write(
+            o->descriptor_, bufs.buffers(), bufs.count(), 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;
+
+        o->ec_ = ec;
+        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
+        return true;
+      }
+    }
+
+  private:
+    int descriptor_;
+    ConstBufferSequence buffers_;
+  };
+
+  template <typename ConstBufferSequence, typename Handler>
+  class write_op : public write_op_base<ConstBufferSequence>
+  {
+  public:
+    write_op(int descriptor,
+        const ConstBufferSequence& buffers, Handler handler)
+      : write_op_base<ConstBufferSequence>(
+          descriptor, buffers, &write_op::do_complete),
+        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.
+      write_op* o(static_cast<write_op*>(base));
+      typedef handler_alloc_traits<Handler, write_op> alloc_traits;
+      handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+      // Make the upcall if required.
+      if (owner)
+      {
+        // 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_);
+        ptr.reset();
+        asio::detail::fenced_block b;
+        asio_handler_invoke_helpers::invoke(handler, handler);
+      }
+    }
+
+  private:
+    Handler handler_;
+  };
+
+  // Start an asynchronous write. The data being sent must be valid for the
+  // lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename Handler>
+  void async_write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef write_op<ConstBufferSequence, Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr, impl.descriptor_, buffers, handler);
+
+    start_op(impl, reactor::write_op, ptr.get(), true,
+        buffer_sequence_adapter<asio::const_buffer,
+          ConstBufferSequence>::all_empty(buffers));
+    ptr.release();
+  }
+
+  // Start an asynchronous wait until data can be written without blocking.
+  template <typename Handler>
+  void async_write_some(implementation_type& impl,
+      const null_buffers&, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef null_buffers_op<Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+    start_op(impl, reactor::write_op, ptr.get(), false, false);
+    ptr.release();
+  }
+
+  // Read some data from the stream. Returns the number of bytes read.
+  template <typename MutableBufferSequence>
+  size_t read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, asio::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = asio::error::bad_descriptor;
+      return 0;
+    }
+
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(buffers);
+
+    // A request to read_some 0 bytes on a stream is a no-op.
+    if (bufs.all_empty())
+    {
+      ec = asio::error_code();
+      return 0;
+    }
+
+    // Read some data.
+    for (;;)
+    {
+      // Try to complete the operation without blocking.
+      int bytes_read = descriptor_ops::scatter_read(
+          impl.descriptor_, bufs.buffers(), bufs.count(), ec);
+
+      // Check if operation succeeded.
+      if (bytes_read > 0)
+        return bytes_read;
+
+      // Check for EOF.
+      if (bytes_read == 0)
+      {
+        ec = asio::error::eof;
+        return 0;
+      }
+
+      // Operation failed.
+      if ((impl.flags_ & implementation_type::user_set_non_blocking)
+          || (ec != asio::error::would_block
+            && ec != asio::error::try_again))
+        return 0;
+
+      // Wait for descriptor to become ready.
+      if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0)
+        return 0;
+    }
+  }
+
+  // Wait until data can be read without blocking.
+  size_t read_some(implementation_type& impl,
+      const null_buffers&, asio::error_code& ec)
+  {
+    if (!is_open(impl))
+    {
+      ec = asio::error::bad_descriptor;
+      return 0;
+    }
+
+    // Wait for descriptor to become ready.
+    descriptor_ops::poll_read(impl.descriptor_, ec);
+
+    return 0;
+  }
+
+  template <typename MutableBufferSequence>
+  class read_op_base : public reactor_op
+  {
+  public:
+    read_op_base(int descriptor,
+        const MutableBufferSequence& buffers, func_type complete_func)
+      : reactor_op(&read_op_base::do_perform, complete_func),
+        descriptor_(descriptor),
+        buffers_(buffers)
+    {
+    }
+
+    static bool do_perform(reactor_op* base)
+    {
+      read_op_base* o(static_cast<read_op_base*>(base));
+
+      buffer_sequence_adapter<asio::mutable_buffer,
+          MutableBufferSequence> bufs(o->buffers_);
+
+      for (;;)
+      {
+        // Read some data.
+        asio::error_code ec;
+        int bytes = descriptor_ops::scatter_read(
+            o->descriptor_, bufs.buffers(), bufs.count(), ec);
+        if (bytes == 0)
+          ec = asio::error::eof;
+
+        // 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;
+
+        o->ec_ = ec;
+        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
+        return true;
+      }
+    }
+
+  private:
+    int descriptor_;
+    MutableBufferSequence buffers_;
+  };
+
+  template <typename MutableBufferSequence, typename Handler>
+  class read_op : public read_op_base<MutableBufferSequence>
+  {
+  public:
+    read_op(int descriptor,
+        const MutableBufferSequence& buffers, Handler handler)
+      : read_op_base<MutableBufferSequence>(
+          descriptor, buffers, &read_op::do_complete),
+        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.
+      read_op* o(static_cast<read_op*>(base));
+      typedef handler_alloc_traits<Handler, read_op> alloc_traits;
+      handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+      // Make the upcall if required.
+      if (owner)
+      {
+        // 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_);
+        ptr.reset();
+        asio::detail::fenced_block b;
+        asio_handler_invoke_helpers::invoke(handler, handler);
+      }
+    }
+
+  private:
+    Handler handler_;
+  };
+
+  // Start an asynchronous read. The buffer for the data being read must be
+  // valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename Handler>
+  void async_read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef read_op<MutableBufferSequence, Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr,
+        impl.descriptor_, buffers, handler);
+
+    start_op(impl, reactor::read_op, ptr.get(), true,
+        buffer_sequence_adapter<asio::mutable_buffer,
+          MutableBufferSequence>::all_empty(buffers));
+    ptr.release();
+  }
+
+  // Wait until data can be read without blocking.
+  template <typename Handler>
+  void async_read_some(implementation_type& impl,
+      const null_buffers&, Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef null_buffers_op<Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+
+    start_op(impl, reactor::read_op, ptr.get(), false, false);
+    ptr.release();
+  }
+
+private:
+  // Start the asynchronous operation.
+  void start_op(implementation_type& impl, int op_type,
+      reactor_op* op, bool non_blocking, bool noop)
+  {
+    if (!noop)
+    {
+      if (is_open(impl))
+      {
+        if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_))
+        {
+          reactor_.start_op(op_type, impl.descriptor_,
+              impl.reactor_data_, op, non_blocking);
+          return;
+        }
+      }
+      else
+        op->ec_ = asio::error::bad_descriptor;
+    }
+
+    io_service_impl_.post_immediate_completion(op);
+  }
+
+  // Determine whether the descriptor has been set non-blocking.
+  bool is_non_blocking(implementation_type& impl) const
+  {
+    return (impl.flags_ & implementation_type::non_blocking);
+  }
+
+  // Set the internal non-blocking flag.
+  bool set_non_blocking(implementation_type& impl,
+      asio::error_code& ec)
+  {
+    ioctl_arg_type non_blocking = 1;
+    if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+      return false;
+    impl.flags_ |= implementation_type::internal_non_blocking;
+    return true;
+  }
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_impl_;
+
+  // The selector that performs event demultiplexing for the service.
+  reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP

+ 261 - 0
ext/asio/asio/detail/reactive_serial_port_service.hpp

@@ -0,0 +1,261 @@
+//
+// reactive_serial_port_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.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_SERIAL_PORT_SERVICE_HPP
+#define ASIO_DETAIL_REACTIVE_SERIAL_PORT_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 <cstring>
+#include <string>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/serial_port_base.hpp"
+
+#if defined(ASIO_HAS_SERIAL_PORT) \
+  && !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/reactive_descriptor_service.hpp"
+
+namespace asio {
+namespace detail {
+
+// Extend reactive_descriptor_service to provide serial port support.
+class reactive_serial_port_service
+{
+public:
+  // The native type of a serial port.
+  typedef reactive_descriptor_service::native_type native_type;
+
+  // The implementation type of the serial port.
+  typedef reactive_descriptor_service::implementation_type implementation_type;
+
+  reactive_serial_port_service(asio::io_service& io_service)
+    : descriptor_service_(io_service)
+  {
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    descriptor_service_.shutdown_service();
+  }
+
+  // Construct a new handle implementation.
+  void construct(implementation_type& impl)
+  {
+    descriptor_service_.construct(impl);
+  }
+
+  // Destroy a handle implementation.
+  void destroy(implementation_type& impl)
+  {
+    descriptor_service_.destroy(impl);
+  }
+
+  // Open the serial port using the specified device name.
+  asio::error_code open(implementation_type& impl,
+      const std::string& device, asio::error_code& ec)
+  {
+    if (is_open(impl))
+    {
+      ec = asio::error::already_open;
+      return ec;
+    }
+
+    int fd = descriptor_ops::open(device.c_str(),
+        O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
+    if (fd < 0)
+      return ec;
+
+    int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
+    if (s >= 0)
+      s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
+    if (s < 0)
+    {
+      asio::error_code ignored_ec;
+      descriptor_ops::close(fd, ignored_ec);
+      return ec;
+    }
+  
+    // Set up default serial port options.
+    termios ios;
+    descriptor_ops::clear_error(ec);
+    s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
+    if (s >= 0)
+    {
+#if defined(_BSD_SOURCE)
+      ::cfmakeraw(&ios);
+#else
+      ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
+          | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+      ios.c_oflag &= ~OPOST;
+      ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+      ios.c_cflag &= ~(CSIZE | PARENB);
+      ios.c_cflag |= CS8;
+#endif
+      ios.c_iflag |= IGNPAR;
+      ios.c_cflag |= CREAD | CLOCAL;
+      descriptor_ops::clear_error(ec);
+      s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
+    }
+    if (s < 0)
+    {
+      asio::error_code ignored_ec;
+      descriptor_ops::close(fd, ignored_ec);
+      return ec;
+    }
+  
+    // We're done. Take ownership of the serial port descriptor.
+    if (descriptor_service_.assign(impl, fd, ec))
+    {
+      asio::error_code ignored_ec;
+      descriptor_ops::close(fd, ignored_ec);
+    }
+
+    return ec;
+  }
+
+  // Assign a native handle to a handle implementation.
+  asio::error_code assign(implementation_type& impl,
+      const native_type& native_descriptor, asio::error_code& ec)
+  {
+    return descriptor_service_.assign(impl, native_descriptor, ec);
+  }
+
+  // Determine whether the handle is open.
+  bool is_open(const implementation_type& impl) const
+  {
+    return descriptor_service_.is_open(impl);
+  }
+
+  // Destroy a handle implementation.
+  asio::error_code close(implementation_type& impl,
+      asio::error_code& ec)
+  {
+    return descriptor_service_.close(impl, ec);
+  }
+
+  // Get the native handle representation.
+  native_type native(implementation_type& impl)
+  {
+    return descriptor_service_.native(impl);
+  }
+
+  // Cancel all operations associated with the handle.
+  asio::error_code cancel(implementation_type& impl,
+      asio::error_code& ec)
+  {
+    return descriptor_service_.cancel(impl, ec);
+  }
+
+  // Set an option on the serial port.
+  template <typename SettableSerialPortOption>
+  asio::error_code set_option(implementation_type& impl,
+      const SettableSerialPortOption& option, asio::error_code& ec)
+  {
+    termios ios;
+    descriptor_ops::clear_error(ec);
+    descriptor_ops::error_wrapper(::tcgetattr(
+          descriptor_service_.native(impl), &ios), ec);
+    if (ec)
+      return ec;
+
+    if (option.store(ios, ec))
+      return ec;
+
+    descriptor_ops::clear_error(ec);
+    descriptor_ops::error_wrapper(::tcsetattr(
+          descriptor_service_.native(impl), TCSANOW, &ios), ec);
+    return ec;
+  }
+
+  // Get an option from the serial port.
+  template <typename GettableSerialPortOption>
+  asio::error_code get_option(const implementation_type& impl,
+      GettableSerialPortOption& option, asio::error_code& ec) const
+  {
+    termios ios;
+    descriptor_ops::clear_error(ec);
+    descriptor_ops::error_wrapper(::tcgetattr(
+          descriptor_service_.native(impl), &ios), ec);
+    if (ec)
+      return ec;
+
+    return option.load(ios, ec);
+  }
+
+  // Send a break sequence to the serial port.
+  asio::error_code send_break(implementation_type& impl,
+      asio::error_code& ec)
+  {
+    descriptor_ops::clear_error(ec);
+    descriptor_ops::error_wrapper(::tcsendbreak(
+          descriptor_service_.native(impl), 0), ec);
+    return ec;
+  }
+
+  // Write the given data. Returns the number of bytes sent.
+  template <typename ConstBufferSequence>
+  size_t write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, asio::error_code& ec)
+  {
+    return descriptor_service_.write_some(impl, buffers, ec);
+  }
+
+  // Start an asynchronous write. The data being written must be valid for the
+  // lifetime of the asynchronous operation.
+  template <typename ConstBufferSequence, typename Handler>
+  void async_write_some(implementation_type& impl,
+      const ConstBufferSequence& buffers, Handler handler)
+  {
+    descriptor_service_.async_write_some(impl, buffers, handler);
+  }
+
+  // Read some data. Returns the number of bytes received.
+  template <typename MutableBufferSequence>
+  size_t read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, asio::error_code& ec)
+  {
+    return descriptor_service_.read_some(impl, buffers, ec);
+  }
+
+  // Start an asynchronous read. The buffer for the data being received must be
+  // valid for the lifetime of the asynchronous operation.
+  template <typename MutableBufferSequence, typename Handler>
+  void async_read_some(implementation_type& impl,
+      const MutableBufferSequence& buffers, Handler handler)
+  {
+    descriptor_service_.async_read_some(impl, buffers, handler);
+  }
+
+private:
+  // The implementation used for initiating asynchronous operations.
+  reactive_descriptor_service descriptor_service_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+       //   && !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP

File diff suppressed because it is too large
+ 1744 - 0
ext/asio/asio/detail/reactive_socket_service.hpp


+ 34 - 0
ext/asio/asio/detail/reactor.hpp

@@ -0,0 +1,34 @@
+//
+// reactor.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_REACTOR_HPP
+#define ASIO_DETAIL_REACTOR_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/reactor_fwd.hpp"
+
+#if defined(ASIO_HAS_EPOLL)
+# include "asio/detail/epoll_reactor.hpp"
+#elif defined(ASIO_HAS_KQUEUE)
+# include "asio/detail/kqueue_reactor.hpp"
+#elif defined(ASIO_HAS_DEV_POLL)
+# include "asio/detail/dev_poll_reactor.hpp"
+#else
+# include "asio/detail/select_reactor.hpp"
+#endif
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTOR_HPP

+ 46 - 0
ext/asio/asio/detail/reactor_fwd.hpp

@@ -0,0 +1,46 @@
+//
+// reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_REACTOR_FWD_HPP
+#define ASIO_DETAIL_REACTOR_FWD_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/dev_poll_reactor_fwd.hpp"
+#include "asio/detail/epoll_reactor_fwd.hpp"
+#include "asio/detail/kqueue_reactor_fwd.hpp"
+#include "asio/detail/select_reactor_fwd.hpp"
+#include "asio/detail/win_iocp_io_service_fwd.hpp"
+
+namespace asio {
+namespace detail {
+
+#if defined(ASIO_HAS_IOCP)
+typedef select_reactor<true> reactor;
+#elif defined(ASIO_HAS_EPOLL)
+typedef epoll_reactor reactor;
+#elif defined(ASIO_HAS_KQUEUE)
+typedef kqueue_reactor reactor;
+#elif defined(ASIO_HAS_DEV_POLL)
+typedef dev_poll_reactor reactor;
+#else
+typedef select_reactor<false> reactor;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTOR_FWD_HPP

+ 60 - 0
ext/asio/asio/detail/reactor_op.hpp

@@ -0,0 +1,60 @@
+//
+// reactor_op.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_REACTOR_OP_HPP
+#define ASIO_DETAIL_REACTOR_OP_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/operation.hpp"
+
+namespace asio {
+namespace detail {
+
+class reactor_op
+  : public operation
+{
+public:
+  // The error code to be passed to the completion handler.
+  asio::error_code ec_;
+
+  // The number of bytes transferred, to be passed to the completion handler.
+  std::size_t bytes_transferred_;
+
+  // Perform the operation. Returns true if it is finished.
+  bool perform()
+  {
+    return perform_func_(this);
+  }
+
+protected:
+  typedef bool (*perform_func_type)(reactor_op*);
+
+  reactor_op(perform_func_type perform_func, func_type complete_func)
+    : operation(complete_func),
+      bytes_transferred_(0),
+      perform_func_(perform_func)
+  {
+  }
+
+private:
+  perform_func_type perform_func_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTOR_OP_HPP

+ 199 - 0
ext/asio/asio/detail/reactor_op_queue.hpp

@@ -0,0 +1,199 @@
+//
+// reactor_op_queue.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_REACTOR_OP_QUEUE_HPP
+#define ASIO_DETAIL_REACTOR_OP_QUEUE_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/error.hpp"
+#include "asio/detail/hash_map.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/op_queue.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Descriptor>
+class reactor_op_queue
+  : private noncopyable
+{
+public:
+  // Constructor.
+  reactor_op_queue()
+    : operations_()
+  {
+  }
+
+  // Add a new operation to the queue. Returns true if this is the only
+  // operation for the given descriptor, in which case the reactor's event
+  // demultiplexing function call may need to be interrupted and restarted.
+  bool enqueue_operation(Descriptor descriptor, reactor_op* op)
+  {
+    typedef typename operations_map::iterator iterator;
+    typedef typename operations_map::value_type value_type;
+    std::pair<iterator, bool> entry =
+      operations_.insert(value_type(descriptor, operations()));
+    entry.first->second.op_queue_.push(op);
+    return entry.second;
+  }
+
+  // Cancel all operations associated with the descriptor. Any operations
+  // pending for the descriptor will be notified that they have been cancelled
+  // next time perform_cancellations is called. Returns true if any operations
+  // were cancelled, in which case the reactor's event demultiplexing function
+  // may need to be interrupted and restarted.
+  bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops,
+      const asio::error_code& ec =
+        asio::error::operation_aborted)
+  {
+    typename operations_map::iterator i = operations_.find(descriptor);
+    if (i != operations_.end())
+    {
+      while (reactor_op* op = i->second.op_queue_.front())
+      {
+        op->ec_ = ec;
+        i->second.op_queue_.pop();
+        ops.push(op);
+      }
+      operations_.erase(i);
+      return true;
+    }
+
+    return false;
+  }
+
+  // Whether there are no operations in the queue.
+  bool empty() const
+  {
+    return operations_.empty();
+  }
+
+  // Determine whether there are any operations associated with the descriptor.
+  bool has_operation(Descriptor descriptor) const
+  {
+    return operations_.find(descriptor) != operations_.end();
+  }
+
+  // Perform the operations corresponding to the descriptor. Returns true if
+  // there are still unfinished operations queued for the descriptor.
+  bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)
+  {
+    typename operations_map::iterator i = operations_.find(descriptor);
+    if (i != operations_.end())
+    {
+      while (reactor_op* op = i->second.op_queue_.front())
+      {
+        if (op->perform())
+        {
+          i->second.op_queue_.pop();
+          ops.push(op);
+        }
+        else
+        {
+          return true;
+        }
+      }
+      operations_.erase(i);
+    }
+    return false;
+  }
+
+  // Fill a descriptor set with the descriptors corresponding to each active
+  // operation. The op_queue is used only when descriptors fail to be added to
+  // the descriptor set.
+  template <typename Descriptor_Set>
+  void get_descriptors(Descriptor_Set& descriptors, op_queue<operation>& ops)
+  {
+    typename operations_map::iterator i = operations_.begin();
+    while (i != operations_.end())
+    {
+      Descriptor descriptor = i->first;
+      ++i;
+      if (!descriptors.set(descriptor))
+      {
+        asio::error_code ec(error::fd_set_failure);
+        cancel_operations(descriptor, ops, ec);
+      }
+    }
+  }
+
+  // Perform the operations corresponding to the ready file descriptors
+  // contained in the given descriptor set.
+  template <typename Descriptor_Set>
+  void perform_operations_for_descriptors(
+      const Descriptor_Set& descriptors, op_queue<operation>& ops)
+  {
+    typename operations_map::iterator i = operations_.begin();
+    while (i != operations_.end())
+    {
+      typename operations_map::iterator op_iter = i++;
+      if (descriptors.is_set(op_iter->first))
+      {
+        while (reactor_op* op = op_iter->second.op_queue_.front())
+        {
+          if (op->perform())
+          {
+            op_iter->second.op_queue_.pop();
+            ops.push(op);
+          }
+          else
+          {
+            break;
+          }
+        }
+
+        if (op_iter->second.op_queue_.empty())
+          operations_.erase(op_iter);
+      }
+    }
+  }
+
+  // Get all operations owned by the queue.
+  void get_all_operations(op_queue<operation>& ops)
+  {
+    typename operations_map::iterator i = operations_.begin();
+    while (i != operations_.end())
+    {
+      typename operations_map::iterator op_iter = i++;
+      ops.push(op_iter->second.op_queue_);
+      operations_.erase(op_iter);
+    }
+  }
+
+private:
+  struct operations
+  {
+    operations() {}
+    operations(const operations&) {}
+    void operator=(const operations&) {}
+
+    // The operations waiting on the desccriptor.
+    op_queue<reactor_op> op_queue_;
+  };
+
+  // The type for a map of operations.
+  typedef hash_map<Descriptor, operations> operations_map;
+
+  // The operations that are currently executing asynchronously.
+  operations_map operations_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP

+ 442 - 0
ext/asio/asio/detail/resolver_service.hpp

@@ -0,0 +1,442 @@
+//
+// resolver_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_RESOLVER_SERVICE_HPP
+#define ASIO_DETAIL_RESOLVER_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 <cstring>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/ip/basic_resolver_iterator.hpp"
+#include "asio/ip/basic_resolver_query.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/service_base.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/thread.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class resolver_service
+  : public asio::detail::service_base<resolver_service<Protocol> >
+{
+private:
+  // Helper class to perform exception-safe cleanup of addrinfo objects.
+  class auto_addrinfo
+    : private asio::detail::noncopyable
+  {
+  public:
+    explicit auto_addrinfo(asio::detail::addrinfo_type* ai)
+      : ai_(ai)
+    {
+    }
+
+    ~auto_addrinfo()
+    {
+      if (ai_)
+        socket_ops::freeaddrinfo(ai_);
+    }
+
+    operator asio::detail::addrinfo_type*()
+    {
+      return ai_;
+    }
+
+  private:
+    asio::detail::addrinfo_type* ai_;
+  };
+
+public:
+  // The implementation type of the resolver. The shared pointer is used as a
+  // cancellation token to indicate to the background thread that the operation
+  // has been cancelled.
+  typedef boost::shared_ptr<void> implementation_type;
+  struct noop_deleter { void operator()(void*) {} };
+
+  // The endpoint type.
+  typedef typename Protocol::endpoint endpoint_type;
+
+  // The query type.
+  typedef asio::ip::basic_resolver_query<Protocol> query_type;
+
+  // The iterator type.
+  typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+
+  // Constructor.
+  resolver_service(asio::io_service& io_service)
+    : asio::detail::service_base<
+        resolver_service<Protocol> >(io_service),
+      mutex_(),
+      io_service_impl_(asio::use_service<io_service_impl>(io_service)),
+      work_io_service_(new asio::io_service),
+      work_io_service_impl_(asio::use_service<
+          io_service_impl>(*work_io_service_)),
+      work_(new asio::io_service::work(*work_io_service_)),
+      work_thread_(0)
+  {
+  }
+
+  // Destructor.
+  ~resolver_service()
+  {
+    shutdown_service();
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    work_.reset();
+    if (work_io_service_)
+    {
+      work_io_service_->stop();
+      if (work_thread_)
+      {
+        work_thread_->join();
+        work_thread_.reset();
+      }
+      work_io_service_.reset();
+    }
+  }
+
+  // Construct a new resolver implementation.
+  void construct(implementation_type& impl)
+  {
+    impl.reset(static_cast<void*>(0), noop_deleter());
+  }
+
+  // Destroy a resolver implementation.
+  void destroy(implementation_type&)
+  {
+  }
+
+  // Cancel pending asynchronous operations.
+  void cancel(implementation_type& impl)
+  {
+    impl.reset(static_cast<void*>(0), noop_deleter());
+  }
+
+  // Resolve a query to a list of entries.
+  iterator_type resolve(implementation_type&, const query_type& query,
+      asio::error_code& ec)
+  {
+    asio::detail::addrinfo_type* address_info = 0;
+    std::string host_name = query.host_name();
+    std::string service_name = query.service_name();
+    asio::detail::addrinfo_type hints = query.hints();
+
+    socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
+        service_name.c_str(), &hints, &address_info, ec);
+    auto_addrinfo auto_address_info(address_info);
+
+    if (ec)
+      return iterator_type();
+
+    return iterator_type::create(address_info, host_name, service_name);
+  }
+
+  template <typename Handler>
+  class resolve_op
+    : public operation
+  {
+  public:
+    resolve_op(implementation_type impl, const query_type& query,
+        io_service_impl& io_service_impl, Handler handler)
+      : operation(&resolve_op::do_complete),
+        impl_(impl),
+        query_(query),
+        io_service_impl_(io_service_impl),
+        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.
+      resolve_op* o(static_cast<resolve_op*>(base));
+      typedef handler_alloc_traits<Handler, resolve_op> alloc_traits;
+      handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+      if (owner)
+      {
+        if (owner != &o->io_service_impl_)
+        {
+          // The operation is being run on the worker io_service. Time to
+          // perform the resolver operation.
+        
+          if (o->impl_.expired())
+          {
+            // THe operation has been cancelled.
+            o->ec_ = asio::error::operation_aborted;
+          }
+          else
+          {
+            // Perform the blocking host resolution operation.
+            asio::detail::addrinfo_type* address_info = 0;
+            std::string host_name = o->query_.host_name();
+            std::string service_name = o->query_.service_name();
+            asio::detail::addrinfo_type hints = o->query_.hints();
+            socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
+                service_name.c_str(), &hints, &address_info, o->ec_);
+            auto_addrinfo auto_address_info(address_info);
+            o->iter_ = iterator_type::create(
+              address_info, host_name, service_name);
+          }
+
+          o->io_service_impl_.post_deferred_completion(o);
+          ptr.release();
+        }
+        else
+        {
+          // The operation has been returned to the main io_serice. The
+          // completion handler is ready to be delivered.
+
+          // 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, iterator_type>
+            handler(o->handler_, o->ec_, o->iter_);
+          ptr.reset();
+          asio::detail::fenced_block b;
+          asio_handler_invoke_helpers::invoke(handler, handler);
+        }
+      }
+    }
+
+  private:
+    boost::weak_ptr<void> impl_;
+    query_type query_;
+    io_service_impl& io_service_impl_;
+    Handler handler_;
+    asio::error_code ec_;
+    iterator_type iter_;
+  };
+
+  // Asynchronously resolve a query to a list of entries.
+  template <typename Handler>
+  void async_resolve(implementation_type& impl, const query_type& query,
+      Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef resolve_op<Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr,
+        impl, query, io_service_impl_, handler);
+
+    if (work_io_service_)
+    {
+      start_work_thread();
+      io_service_impl_.work_started();
+      work_io_service_impl_.post_immediate_completion(ptr.get());
+      ptr.release();
+    }
+  }
+
+  // Resolve an endpoint to a list of entries.
+  iterator_type resolve(implementation_type&,
+      const endpoint_type& endpoint, asio::error_code& ec)
+  {
+    // First try resolving with the service name. If that fails try resolving
+    // but allow the service to be returned as a number.
+    char host_name[NI_MAXHOST];
+    char service_name[NI_MAXSERV];
+    int flags = endpoint.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
+    socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
+        host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
+    if (ec)
+    {
+      flags |= NI_NUMERICSERV;
+      socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
+          host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
+    }
+
+    if (ec)
+      return iterator_type();
+
+    return iterator_type::create(endpoint, host_name, service_name);
+  }
+
+  template <typename Handler>
+  class resolve_endpoint_op
+    : public operation
+  {
+  public:
+    resolve_endpoint_op(implementation_type impl, const endpoint_type& ep,
+        io_service_impl& io_service_impl, Handler handler)
+      : operation(&resolve_endpoint_op::do_complete),
+        impl_(impl),
+        ep_(ep),
+        io_service_impl_(io_service_impl),
+        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.
+      resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
+      typedef handler_alloc_traits<Handler, resolve_endpoint_op> alloc_traits;
+      handler_ptr<alloc_traits> ptr(o->handler_, o);
+
+      if (owner)
+      {
+        if (owner != &o->io_service_impl_)
+        {
+          // The operation is being run on the worker io_service. Time to
+          // perform the resolver operation.
+        
+          if (o->impl_.expired())
+          {
+            // THe operation has been cancelled.
+            o->ec_ = asio::error::operation_aborted;
+          }
+          else
+          {
+            // Perform the blocking endoint resolution operation.
+            char host_name[NI_MAXHOST];
+            char service_name[NI_MAXSERV];
+            int flags = o->ep_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
+            socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
+                host_name, NI_MAXHOST, service_name,
+                NI_MAXSERV, flags, o->ec_);
+            if (o->ec_)
+            {
+              flags |= NI_NUMERICSERV;
+              socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
+                  host_name, NI_MAXHOST, service_name,
+                  NI_MAXSERV, flags, o->ec_);
+            }
+            o->iter_ = iterator_type::create(o->ep_, host_name, service_name);
+          }
+
+          o->io_service_impl_.post_deferred_completion(o);
+          ptr.release();
+        }
+        else
+        {
+          // The operation has been returned to the main io_serice. The
+          // completion handler is ready to be delivered.
+
+          // 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, iterator_type>
+            handler(o->handler_, o->ec_, o->iter_);
+          ptr.reset();
+          asio::detail::fenced_block b;
+          asio_handler_invoke_helpers::invoke(handler, handler);
+        }
+      }
+    }
+
+  private:
+    boost::weak_ptr<void> impl_;
+    endpoint_type ep_;
+    io_service_impl& io_service_impl_;
+    Handler handler_;
+    asio::error_code ec_;
+    iterator_type iter_;
+  };
+
+  // Asynchronously resolve an endpoint to a list of entries.
+  template <typename Handler>
+  void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
+      Handler handler)
+  {
+    // Allocate and construct an operation to wrap the handler.
+    typedef resolve_endpoint_op<Handler> value_type;
+    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+    raw_handler_ptr<alloc_traits> raw_ptr(handler);
+    handler_ptr<alloc_traits> ptr(raw_ptr,
+        impl, endpoint, io_service_impl_, handler);
+
+    if (work_io_service_)
+    {
+      start_work_thread();
+      io_service_impl_.work_started();
+      work_io_service_impl_.post_immediate_completion(ptr.get());
+      ptr.release();
+    }
+  }
+
+private:
+  // Helper class to run the work io_service in a thread.
+  class work_io_service_runner
+  {
+  public:
+    work_io_service_runner(asio::io_service& io_service)
+      : io_service_(io_service) {}
+    void operator()() { io_service_.run(); }
+  private:
+    asio::io_service& io_service_;
+  };
+
+  // Start the work thread if it's not already running.
+  void start_work_thread()
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    if (!work_thread_)
+    {
+      work_thread_.reset(new asio::detail::thread(
+            work_io_service_runner(*work_io_service_)));
+    }
+  }
+
+  // Mutex to protect access to internal data.
+  asio::detail::mutex mutex_;
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_impl_;
+
+  // Private io_service used for performing asynchronous host resolution.
+  boost::scoped_ptr<asio::io_service> work_io_service_;
+
+  // The work io_service implementation used to post completions.
+  io_service_impl& work_io_service_impl_;
+
+  // Work for the private io_service to perform.
+  boost::scoped_ptr<asio::io_service::work> work_;
+
+  // Thread used for running the work io_service's run loop.
+  boost::scoped_ptr<asio::detail::thread> work_thread_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_RESOLVER_SERVICE_HPP

+ 91 - 0
ext/asio/asio/detail/scoped_lock.hpp

@@ -0,0 +1,91 @@
+//
+// scoped_lock.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SCOPED_LOCK_HPP
+#define ASIO_DETAIL_SCOPED_LOCK_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/noncopyable.hpp"
+
+namespace asio {
+namespace detail {
+
+// Helper class to lock and unlock a mutex automatically.
+template <typename Mutex>
+class scoped_lock
+  : private noncopyable
+{
+public:
+  // Constructor acquires the lock.
+  scoped_lock(Mutex& m)
+    : mutex_(m)
+  {
+    mutex_.lock();
+    locked_ = true;
+  }
+
+  // Destructor releases the lock.
+  ~scoped_lock()
+  {
+    if (locked_)
+      mutex_.unlock();
+  }
+
+  // Explicitly acquire the lock.
+  void lock()
+  {
+    if (!locked_)
+    {
+      mutex_.lock();
+      locked_ = true;
+    }
+  }
+
+  // Explicitly release the lock.
+  void unlock()
+  {
+    if (locked_)
+    {
+      mutex_.unlock();
+      locked_ = false;
+    }
+  }
+
+  // Test whether the lock is held.
+  bool locked() const
+  {
+    return locked_;
+  }
+
+  // Get the underlying mutex.
+  Mutex& mutex()
+  {
+    return mutex_;
+  }
+
+private:
+  // The underlying mutex.
+  Mutex& mutex_;
+
+  // Whether the mutex is currently locked or unlocked.
+  bool locked_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SCOPED_LOCK_HPP

+ 47 - 0
ext/asio/asio/detail/select_interrupter.hpp

@@ -0,0 +1,47 @@
+//
+// select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SELECT_INTERRUPTER_HPP
+#define ASIO_DETAIL_SELECT_INTERRUPTER_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include "asio/detail/socket_select_interrupter.hpp"
+#else
+# include "asio/detail/eventfd_select_interrupter.hpp"
+# include "asio/detail/pipe_select_interrupter.hpp"
+#endif
+
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef socket_select_interrupter select_interrupter;
+#elif defined(ASIO_HAS_EVENTFD)
+typedef eventfd_select_interrupter select_interrupter;
+#else
+typedef pipe_select_interrupter select_interrupter;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP

+ 374 - 0
ext/asio/asio/detail/select_reactor.hpp

@@ -0,0 +1,374 @@
+//
+// select_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SELECT_REACTOR_HPP
+#define ASIO_DETAIL_SELECT_REACTOR_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/socket_types.hpp" // Must come before posix_time.
+
+#include "asio/detail/push_options.hpp"
+#include <cstddef>
+#include <boost/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/io_service.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fd_set_adapter.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/op_queue.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/reactor_op_queue.hpp"
+#include "asio/detail/select_interrupter.hpp"
+#include "asio/detail/select_reactor_fwd.hpp"
+#include "asio/detail/service_base.hpp"
+#include "asio/detail/signal_blocker.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/thread.hpp"
+#include "asio/detail/timer_op.hpp"
+#include "asio/detail/timer_queue_base.hpp"
+#include "asio/detail/timer_queue_fwd.hpp"
+#include "asio/detail/timer_queue_set.hpp"
+
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class select_reactor
+  : public asio::detail::service_base<select_reactor<Own_Thread> >
+{
+public:
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  enum { read_op = 0, write_op = 1, except_op = 2,
+    max_select_ops = 3, connect_op = 3, max_ops = 4 };
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  enum { read_op = 0, write_op = 1, except_op = 2,
+    max_select_ops = 3, connect_op = 1, max_ops = 3 };
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+  // Per-descriptor data.
+  struct per_descriptor_data
+  {
+  };
+
+  // Constructor.
+  select_reactor(asio::io_service& io_service)
+    : asio::detail::service_base<
+        select_reactor<Own_Thread> >(io_service),
+      io_service_(use_service<io_service_impl>(io_service)),
+      mutex_(),
+      interrupter_(),
+      stop_thread_(false),
+      thread_(0),
+      shutdown_(false)
+  {
+    if (Own_Thread)
+    {
+      asio::detail::signal_blocker sb;
+      thread_ = new asio::detail::thread(
+          bind_handler(&select_reactor::call_run_thread, this));
+    }
+  }
+
+  // Destructor.
+  ~select_reactor()
+  {
+    shutdown_service();
+  }
+
+  // Destroy all user-defined handler objects owned by the service.
+  void shutdown_service()
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    shutdown_ = true;
+    stop_thread_ = true;
+    lock.unlock();
+
+    if (Own_Thread)
+    {
+      if (thread_)
+      {
+        interrupter_.interrupt();
+        thread_->join();
+        delete thread_;
+        thread_ = 0;
+      }
+    }
+
+    op_queue<operation> ops;
+
+    for (int i = 0; i < max_ops; ++i)
+      op_queue_[i].get_all_operations(ops);
+
+    timer_queues_.get_all_timers(ops);
+  }
+
+  // Initialise the task, but only if the reactor is not in its own thread.
+  void init_task()
+  {
+    io_service_.init_task();
+  }
+
+  // Register a socket with the reactor. Returns 0 on success, system error
+  // code on failure.
+  int register_descriptor(socket_type, per_descriptor_data&)
+  {
+    return 0;
+  }
+
+  // Start a new operation. The reactor operation will be performed when the
+  // given descriptor is flagged as ready, or an error has occurred.
+  void start_op(int op_type, socket_type descriptor,
+      per_descriptor_data&, reactor_op* op, bool)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    if (!shutdown_)
+    {
+      bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+      io_service_.work_started();
+      if (first)
+        interrupter_.interrupt();
+    }
+  }
+
+  // Cancel all operations associated with the given descriptor. The
+  // handlers associated with the descriptor will be invoked with the
+  // operation_aborted error.
+  void cancel_ops(socket_type descriptor, per_descriptor_data&)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+  }
+
+  // Cancel any operations that are running against the descriptor and remove
+  // its registration from the reactor.
+  void close_descriptor(socket_type descriptor, per_descriptor_data&)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+  }
+
+  // Add a new timer queue to the reactor.
+  template <typename Time_Traits>
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    timer_queues_.insert(&timer_queue);
+  }
+
+  // Remove a timer queue from the reactor.
+  template <typename Time_Traits>
+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    timer_queues_.erase(&timer_queue);
+  }
+
+  // Schedule a new operation in the given timer queue to expire at the
+  // specified absolute time.
+  template <typename Time_Traits>
+  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+      const typename Time_Traits::time_type& time, timer_op* op, void* token)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    if (!shutdown_)
+    {
+      bool earliest = timer_queue.enqueue_timer(time, op, token);
+      io_service_.work_started();
+      if (earliest)
+        interrupter_.interrupt();
+    }
+  }
+
+  // Cancel the timer operations associated with the given token. Returns the
+  // number of operations that have been posted or dispatched.
+  template <typename Time_Traits>
+  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+    op_queue<operation> ops;
+    std::size_t n = timer_queue.cancel_timer(token, ops);
+    lock.unlock();
+    io_service_.post_deferred_completions(ops);
+    return n;
+  }
+
+  // Run select once until interrupted or events are ready to be dispatched.
+  void run(bool block, op_queue<operation>& ops)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+
+    // Check if the thread is supposed to stop.
+    if (Own_Thread)
+      if (stop_thread_)
+        return;
+
+    // Set up the descriptor sets.
+    fd_set_adapter fds[max_select_ops];
+    fds[read_op].set(interrupter_.read_descriptor());
+    socket_type max_fd = 0;
+    bool have_work_to_do = !timer_queues_.all_empty();
+    for (int i = 0; i < max_select_ops; ++i)
+    {
+      have_work_to_do = have_work_to_do || !op_queue_[i].empty();
+      op_queue_[i].get_descriptors(fds[i], ops);
+      if (fds[i].max_descriptor() > max_fd)
+        max_fd = fds[i].max_descriptor();
+    }
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    // Connection operations on Windows use both except and write fd_sets.
+    have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
+    op_queue_[connect_op].get_descriptors(fds[write_op], ops);
+    if (fds[write_op].max_descriptor() > max_fd)
+      max_fd = fds[write_op].max_descriptor();
+    op_queue_[connect_op].get_descriptors(fds[except_op], ops);
+    if (fds[except_op].max_descriptor() > max_fd)
+      max_fd = fds[except_op].max_descriptor();
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+    // We can return immediately if there's no work to do and the reactor is
+    // not supposed to block.
+    if (!block && !have_work_to_do)
+      return;
+
+    // Determine how long to block while waiting for events.
+    timeval tv_buf = { 0, 0 };
+    timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
+
+    lock.unlock();
+
+    // Block on the select call until descriptors become ready.
+    asio::error_code ec;
+    int retval = socket_ops::select(static_cast<int>(max_fd + 1),
+        fds[read_op], fds[write_op], fds[except_op], tv, ec);
+
+    // Reset the interrupter.
+    if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))
+      interrupter_.reset();
+
+    lock.lock();
+
+    // Dispatch all ready operations.
+    if (retval > 0)
+    {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+      // Connection operations on Windows use both except and write fd_sets.
+      op_queue_[connect_op].perform_operations_for_descriptors(
+          fds[except_op], ops);
+      op_queue_[connect_op].perform_operations_for_descriptors(
+          fds[write_op], ops);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+      // Exception operations must be processed first to ensure that any
+      // out-of-band data is read before normal data.
+      for (int i = max_select_ops - 1; i >= 0; --i)
+        op_queue_[i].perform_operations_for_descriptors(fds[i], ops);
+    }
+    timer_queues_.get_ready_timers(ops);
+  }
+
+  // Interrupt the select loop.
+  void interrupt()
+  {
+    interrupter_.interrupt();
+  }
+
+private:
+  // Run the select loop in the thread.
+  void run_thread()
+  {
+    if (Own_Thread)
+    {
+      asio::detail::mutex::scoped_lock lock(mutex_);
+      while (!stop_thread_)
+      {
+        lock.unlock();
+        op_queue<operation> ops;
+        run(true, ops);
+        io_service_.post_deferred_completions(ops);
+        lock.lock();
+      }
+    }
+  }
+
+  // Entry point for the select loop thread.
+  static void call_run_thread(select_reactor* reactor)
+  {
+    if (Own_Thread)
+    {
+      reactor->run_thread();
+    }
+  }
+
+  // Get the timeout value for the select call.
+  timeval* get_timeout(timeval& tv)
+  {
+    // By default we will wait no longer than 5 minutes. This will ensure that
+    // any changes to the system clock are detected after no longer than this.
+    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+    tv.tv_sec = usec / 1000000;
+    tv.tv_usec = usec % 1000000;
+    return &tv;
+  }
+
+  // Cancel all operations associated with the given descriptor. This function
+  // does not acquire the select_reactor's mutex.
+  void cancel_ops_unlocked(socket_type descriptor,
+      const asio::error_code& ec)
+  {
+    bool need_interrupt = false;
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+      need_interrupt = op_queue_[i].cancel_operations(
+          descriptor, ops, ec) || need_interrupt;
+    io_service_.post_deferred_completions(ops);
+    if (need_interrupt)
+      interrupter_.interrupt();
+  }
+
+  // The io_service implementation used to post completions.
+  io_service_impl& io_service_;
+
+  // Mutex to protect access to internal data.
+  asio::detail::mutex mutex_;
+
+  // The interrupter is used to break a blocking select call.
+  select_interrupter interrupter_;
+
+  // The queues of read, write and except operations.
+  reactor_op_queue<socket_type> op_queue_[max_ops];
+
+  // The timer queues.
+  timer_queue_set timer_queues_;
+
+  // Does the reactor loop thread need to stop.
+  bool stop_thread_;
+
+  // The thread that is running the reactor loop.
+  asio::detail::thread* thread_;
+
+  // Whether the service has been shut down.
+  bool shutdown_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SELECT_REACTOR_HPP

+ 31 - 0
ext/asio/asio/detail/select_reactor_fwd.hpp

@@ -0,0 +1,31 @@
+//
+// select_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SELECT_REACTOR_FWD_HPP
+#define ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class select_reactor;
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SELECT_REACTOR_FWD_HPP

+ 49 - 0
ext/asio/asio/detail/service_base.hpp

@@ -0,0 +1,49 @@
+//
+// service_base.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SERVICE_BASE_HPP
+#define ASIO_DETAIL_SERVICE_BASE_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/io_service.hpp"
+#include "asio/detail/service_id.hpp"
+
+namespace asio {
+namespace detail {
+
+// Special service base class to keep classes header-file only.
+template <typename Type>
+class service_base
+  : public asio::io_service::service
+{
+public:
+  static asio::detail::service_id<Type> id;
+
+  // Constructor.
+  service_base(asio::io_service& io_service)
+    : asio::io_service::service(io_service)
+  {
+  }
+};
+
+template <typename Type>
+asio::detail::service_id<Type> service_base<Type>::id;
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SERVICE_BASE_HPP

+ 37 - 0
ext/asio/asio/detail/service_id.hpp

@@ -0,0 +1,37 @@
+//
+// service_id.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SERVICE_ID_HPP
+#define ASIO_DETAIL_SERVICE_ID_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/io_service.hpp"
+
+namespace asio {
+namespace detail {
+
+// Special derived service id type to keep classes header-file only.
+template <typename Type>
+class service_id
+  : public asio::io_service::id
+{
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SERVICE_ID_HPP

+ 275 - 0
ext/asio/asio/detail/service_registry.hpp

@@ -0,0 +1,275 @@
+//
+// service_registry.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SERVICE_REGISTRY_HPP
+#define ASIO_DETAIL_SERVICE_REGISTRY_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 <typeinfo>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/io_service.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/service_id.hpp"
+
+#if defined(BOOST_NO_TYPEID)
+# if !defined(ASIO_NO_TYPEID)
+#  define ASIO_NO_TYPEID
+# endif // !defined(ASIO_NO_TYPEID)
+#endif // defined(BOOST_NO_TYPEID)
+
+namespace asio {
+namespace detail {
+
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#  pragma GCC visibility push (default)
+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#endif // defined(__GNUC__)
+
+template <typename T>
+class typeid_wrapper {};
+
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#  pragma GCC visibility pop
+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+#endif // defined(__GNUC__)
+
+class service_registry
+  : private noncopyable
+{
+public:
+  // Constructor.
+  service_registry(asio::io_service& o)
+    : owner_(o),
+      first_service_(0)
+  {
+  }
+
+  // Destructor.
+  ~service_registry()
+  {
+    // Shutdown all services. This must be done in a separate loop before the
+    // services are destroyed since the destructors of user-defined handler
+    // objects may try to access other service objects.
+    asio::io_service::service* service = first_service_;
+    while (service)
+    {
+      service->shutdown_service();
+      service = service->next_;
+    }
+
+    // Destroy all services.
+    while (first_service_)
+    {
+      asio::io_service::service* next_service = first_service_->next_;
+      destroy(first_service_);
+      first_service_ = next_service;
+    }
+  }
+
+  // Get the service object corresponding to the specified service type. Will
+  // create a new service object automatically if no such object already
+  // exists. Ownership of the service object is not transferred to the caller.
+  template <typename Service>
+  Service& use_service()
+  {
+    asio::io_service::service::key key;
+    init_key(key, Service::id);
+    factory_type factory = &service_registry::create<Service>;
+    return *static_cast<Service*>(do_use_service(key, factory));
+  }
+
+  // Add a service object. Returns false on error, in which case ownership of
+  // the object is retained by the caller.
+  template <typename Service>
+  bool add_service(Service* new_service)
+  {
+    asio::io_service::service::key key;
+    init_key(key, Service::id);
+    return do_add_service(key, new_service);
+  }
+
+  // Check whether a service object of the specified type already exists.
+  template <typename Service>
+  bool has_service() const
+  {
+    asio::io_service::service::key key;
+    init_key(key, Service::id);
+    return do_has_service(key);
+  }
+
+private:
+  // Initialise a service's key based on its id.
+  void init_key(asio::io_service::service::key& key,
+      const asio::io_service::id& id)
+  {
+    key.type_info_ = 0;
+    key.id_ = &id;
+  }
+
+#if !defined(ASIO_NO_TYPEID)
+  // Initialise a service's key based on its id.
+  template <typename Service>
+  void init_key(asio::io_service::service::key& key,
+      const asio::detail::service_id<Service>& /*id*/)
+  {
+    key.type_info_ = &typeid(typeid_wrapper<Service>);
+    key.id_ = 0;
+  }
+#endif // !defined(ASIO_NO_TYPEID)
+
+  // Check if a service matches the given id.
+  static bool keys_match(
+      const asio::io_service::service::key& key1,
+      const asio::io_service::service::key& key2)
+  {
+    if (key1.id_ && key2.id_)
+      if (key1.id_ == key2.id_)
+        return true;
+    if (key1.type_info_ && key2.type_info_)
+      if (*key1.type_info_ == *key2.type_info_)
+        return true;
+    return false;
+  }
+
+  // The type of a factory function used for creating a service instance.
+  typedef asio::io_service::service*
+    (*factory_type)(asio::io_service&);
+
+  // Factory function for creating a service instance.
+  template <typename Service>
+  static asio::io_service::service* create(
+      asio::io_service& owner)
+  {
+    return new Service(owner);
+  }
+
+  // Destroy a service instance.
+  static void destroy(asio::io_service::service* service)
+  {
+    delete service;
+  }
+
+  // Helper class to manage service pointers.
+  struct auto_service_ptr
+  {
+    asio::io_service::service* ptr_;
+    ~auto_service_ptr() { destroy(ptr_); }
+  };
+
+  // Get the service object corresponding to the specified service key. Will
+  // create a new service object automatically if no such object already
+  // exists. Ownership of the service object is not transferred to the caller.
+  asio::io_service::service* do_use_service(
+      const asio::io_service::service::key& key,
+      factory_type factory)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+
+    // First see if there is an existing service object with the given key.
+    asio::io_service::service* service = first_service_;
+    while (service)
+    {
+      if (keys_match(service->key_, key))
+        return service;
+      service = service->next_;
+    }
+
+    // Create a new service object. The service registry's mutex is not locked
+    // at this time to allow for nested calls into this function from the new
+    // service's constructor.
+    lock.unlock();
+    auto_service_ptr new_service = { factory(owner_) };
+    new_service.ptr_->key_ = key;
+    lock.lock();
+
+    // Check that nobody else created another service object of the same type
+    // while the lock was released.
+    service = first_service_;
+    while (service)
+    {
+      if (keys_match(service->key_, key))
+        return service;
+      service = service->next_;
+    }
+
+    // Service was successfully initialised, pass ownership to registry.
+    new_service.ptr_->next_ = first_service_;
+    first_service_ = new_service.ptr_;
+    new_service.ptr_ = 0;
+    return first_service_;
+  }
+
+  // Add a service object. Returns false on error, in which case ownership of
+  // the object is retained by the caller.
+  bool do_add_service(
+      const asio::io_service::service::key& key,
+      asio::io_service::service* new_service)
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+
+    // Check if there is an existing service object with the given key.
+    asio::io_service::service* service = first_service_;
+    while (service)
+    {
+      if (keys_match(service->key_, key))
+        return false;
+      service = service->next_;
+    }
+
+    // Take ownership of the service object.
+    new_service->key_ = key;
+    new_service->next_ = first_service_;
+    first_service_ = new_service;
+
+    return true;
+  }
+
+  // Check whether a service object with the specified key already exists.
+  bool do_has_service(const asio::io_service::service::key& key) const
+  {
+    asio::detail::mutex::scoped_lock lock(mutex_);
+
+    asio::io_service::service* service = first_service_;
+    while (service)
+    {
+      if (keys_match(service->key_, key))
+        return true;
+      service = service->next_;
+    }
+
+    return false;
+  }
+
+  // Mutex to protect access to internal data.
+  mutable asio::detail::mutex mutex_;
+
+  // The owner of this service registry and the services it contains.
+  asio::io_service& owner_;
+
+  // The first service in the list of contained services.
+  asio::io_service::service* first_service_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP

+ 30 - 0
ext/asio/asio/detail/service_registry_fwd.hpp

@@ -0,0 +1,30 @@
+//
+// service_registry_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SERVICE_REGISTRY_FWD_HPP
+#define ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class service_registry;
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP

+ 50 - 0
ext/asio/asio/detail/signal_blocker.hpp

@@ -0,0 +1,50 @@
+//
+// signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SIGNAL_BLOCKER_HPP
+#define ASIO_DETAIL_SIGNAL_BLOCKER_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+# include "asio/detail/null_signal_blocker.hpp"
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include "asio/detail/win_signal_blocker.hpp"
+#elif defined(BOOST_HAS_PTHREADS)
+# include "asio/detail/posix_signal_blocker.hpp"
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+typedef null_signal_blocker signal_blocker;
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef win_signal_blocker signal_blocker;
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_signal_blocker signal_blocker;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP

+ 51 - 0
ext/asio/asio/detail/signal_init.hpp

@@ -0,0 +1,51 @@
+//
+// signal_init.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SIGNAL_INIT_HPP
+#define ASIO_DETAIL_SIGNAL_INIT_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/push_options.hpp"
+#include <csignal>
+#include "asio/detail/pop_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <int Signal = SIGPIPE>
+class signal_init
+{
+public:
+  // Constructor.
+  signal_init()
+  {
+    std::signal(Signal, SIG_IGN);
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SIGNAL_INIT_HPP

+ 95 - 0
ext/asio/asio/detail/socket_holder.hpp

@@ -0,0 +1,95 @@
+//
+// socket_holder.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SOCKET_HOLDER_HPP
+#define ASIO_DETAIL_SOCKET_HOLDER_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/noncopyable.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+namespace asio {
+namespace detail {
+
+// Implement the resource acquisition is initialisation idiom for sockets.
+class socket_holder
+  : private noncopyable
+{
+public:
+  // Construct as an uninitialised socket.
+  socket_holder()
+    : socket_(invalid_socket)
+  {
+  }
+
+  // Construct to take ownership of the specified socket.
+  explicit socket_holder(socket_type s)
+    : socket_(s)
+  {
+  }
+
+  // Destructor.
+  ~socket_holder()
+  {
+    if (socket_ != invalid_socket)
+    {
+      asio::error_code ec;
+      socket_ops::close(socket_, ec);
+    }
+  }
+
+  // Get the underlying socket.
+  socket_type get() const
+  {
+    return socket_;
+  }
+
+  // Reset to an uninitialised socket.
+  void reset()
+  {
+    if (socket_ != invalid_socket)
+    {
+      asio::error_code ec;
+      socket_ops::close(socket_, ec);
+      socket_ = invalid_socket;
+    }
+  }
+
+  // Reset to take ownership of the specified socket.
+  void reset(socket_type s)
+  {
+    reset();
+    socket_ = s;
+  }
+
+  // Release ownership of the socket.
+  socket_type release()
+  {
+    socket_type tmp = socket_;
+    socket_ = invalid_socket;
+    return tmp;
+  }
+
+private:
+  // The underlying socket.
+  socket_type socket_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SOCKET_HOLDER_HPP

File diff suppressed because it is too large
+ 1912 - 0
ext/asio/asio/detail/socket_ops.hpp


+ 319 - 0
ext/asio/asio/detail/socket_option.hpp

@@ -0,0 +1,319 @@
+//
+// socket_option.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SOCKET_OPTION_HPP
+#define ASIO_DETAIL_SOCKET_OPTION_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 <cstddef>
+#include <stdexcept>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/socket_types.hpp"
+
+namespace asio {
+namespace detail {
+namespace socket_option {
+
+// Helper template for implementing boolean-based options.
+template <int Level, int Name>
+class boolean
+{
+public:
+  // Default constructor.
+  boolean()
+    : value_(0)
+  {
+  }
+
+  // Construct with a specific option value.
+  explicit boolean(bool v)
+    : value_(v ? 1 : 0)
+  {
+  }
+
+  // Set the current value of the boolean.
+  boolean& operator=(bool v)
+  {
+    value_ = v ? 1 : 0;
+    return *this;
+  }
+
+  // Get the current value of the boolean.
+  bool value() const
+  {
+    return !!value_;
+  }
+
+  // Convert to bool.
+  operator bool() const
+  {
+    return !!value_;
+  }
+
+  // Test for false.
+  bool operator!() const
+  {
+    return !value_;
+  }
+
+  // Get the level of the socket option.
+  template <typename Protocol>
+  int level(const Protocol&) const
+  {
+    return Level;
+  }
+
+  // Get the name of the socket option.
+  template <typename Protocol>
+  int name(const Protocol&) const
+  {
+    return Name;
+  }
+
+  // Get the address of the boolean data.
+  template <typename Protocol>
+  int* data(const Protocol&)
+  {
+    return &value_;
+  }
+
+  // Get the address of the boolean data.
+  template <typename Protocol>
+  const int* data(const Protocol&) const
+  {
+    return &value_;
+  }
+
+  // Get the size of the boolean data.
+  template <typename Protocol>
+  std::size_t size(const Protocol&) const
+  {
+    return sizeof(value_);
+  }
+
+  // Set the size of the boolean data.
+  template <typename Protocol>
+  void resize(const Protocol&, std::size_t s)
+  {
+    // On some platforms (e.g. Windows Vista), the getsockopt function will
+    // return the size of a boolean socket option as one byte, even though a
+    // four byte integer was passed in.
+    switch (s)
+    {
+    case sizeof(char):
+      value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0;
+      break;
+    case sizeof(value_):
+      break;
+    default:
+      {
+        std::length_error ex("boolean socket option resize");
+        boost::throw_exception(ex);
+      }
+    }
+  }
+
+private:
+  int value_;
+};
+
+// Helper template for implementing integer options.
+template <int Level, int Name>
+class integer
+{
+public:
+  // Default constructor.
+  integer()
+    : value_(0)
+  {
+  }
+
+  // Construct with a specific option value.
+  explicit integer(int v)
+    : value_(v)
+  {
+  }
+
+  // Set the value of the int option.
+  integer& operator=(int v)
+  {
+    value_ = v;
+    return *this;
+  }
+
+  // Get the current value of the int option.
+  int value() const
+  {
+    return value_;
+  }
+
+  // Get the level of the socket option.
+  template <typename Protocol>
+  int level(const Protocol&) const
+  {
+    return Level;
+  }
+
+  // Get the name of the socket option.
+  template <typename Protocol>
+  int name(const Protocol&) const
+  {
+    return Name;
+  }
+
+  // Get the address of the int data.
+  template <typename Protocol>
+  int* data(const Protocol&)
+  {
+    return &value_;
+  }
+
+  // Get the address of the int data.
+  template <typename Protocol>
+  const int* data(const Protocol&) const
+  {
+    return &value_;
+  }
+
+  // Get the size of the int data.
+  template <typename Protocol>
+  std::size_t size(const Protocol&) const
+  {
+    return sizeof(value_);
+  }
+
+  // Set the size of the int data.
+  template <typename Protocol>
+  void resize(const Protocol&, std::size_t s)
+  {
+    if (s != sizeof(value_))
+    {
+      std::length_error ex("integer socket option resize");
+      boost::throw_exception(ex);
+    }
+  }
+
+private:
+  int value_;
+};
+
+// Helper template for implementing linger options.
+template <int Level, int Name>
+class linger
+{
+public:
+  // Default constructor.
+  linger()
+  {
+    value_.l_onoff = 0;
+    value_.l_linger = 0;
+  }
+
+  // Construct with specific option values.
+  linger(bool e, int t)
+  {
+    enabled(e);
+    timeout BOOST_PREVENT_MACRO_SUBSTITUTION(t);
+  }
+
+  // Set the value for whether linger is enabled.
+  void enabled(bool value)
+  {
+    value_.l_onoff = value ? 1 : 0;
+  }
+
+  // Get the value for whether linger is enabled.
+  bool enabled() const
+  {
+    return value_.l_onoff != 0;
+  }
+
+  // Set the value for the linger timeout.
+  void timeout BOOST_PREVENT_MACRO_SUBSTITUTION(int value)
+  {
+#if defined(WIN32)
+    value_.l_linger = static_cast<u_short>(value);
+#else
+    value_.l_linger = value;
+#endif
+  }
+
+  // Get the value for the linger timeout.
+  int timeout BOOST_PREVENT_MACRO_SUBSTITUTION() const
+  {
+    return static_cast<int>(value_.l_linger);
+  }
+
+  // Get the level of the socket option.
+  template <typename Protocol>
+  int level(const Protocol&) const
+  {
+    return Level;
+  }
+
+  // Get the name of the socket option.
+  template <typename Protocol>
+  int name(const Protocol&) const
+  {
+    return Name;
+  }
+
+  // Get the address of the linger data.
+  template <typename Protocol>
+  ::linger* data(const Protocol&)
+  {
+    return &value_;
+  }
+
+  // Get the address of the linger data.
+  template <typename Protocol>
+  const ::linger* data(const Protocol&) const
+  {
+    return &value_;
+  }
+
+  // Get the size of the linger data.
+  template <typename Protocol>
+  std::size_t size(const Protocol&) const
+  {
+    return sizeof(value_);
+  }
+
+  // Set the size of the int data.
+  template <typename Protocol>
+  void resize(const Protocol&, std::size_t s)
+  {
+    if (s != sizeof(value_))
+    {
+      std::length_error ex("linger socket option resize");
+      boost::throw_exception(ex);
+    }
+  }
+
+private:
+  ::linger value_;
+};
+
+} // namespace socket_option
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SOCKET_OPTION_HPP

+ 192 - 0
ext/asio/asio/detail/socket_select_interrupter.hpp

@@ -0,0 +1,192 @@
+//
+// socket_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SOCKET_SELECT_INTERRUPTER_HPP
+#define ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_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 <cstdlib>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error.hpp"
+#include "asio/system_error.hpp"
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+
+namespace asio {
+namespace detail {
+
+class socket_select_interrupter
+{
+public:
+  // Constructor.
+  socket_select_interrupter()
+  {
+    asio::error_code ec;
+    socket_holder acceptor(socket_ops::socket(
+          AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+    if (acceptor.get() == invalid_socket)
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    int opt = 1;
+    socket_ops::setsockopt(acceptor.get(),
+        SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
+
+    using namespace std; // For memset.
+    sockaddr_in4_type addr;
+    std::size_t addr_len = sizeof(addr);
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    addr.sin_port = 0;
+    if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
+          addr_len, ec) == socket_error_retval)
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
+          &addr_len, ec) == socket_error_retval)
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    // Some broken firewalls on Windows will intermittently cause getsockname to
+    // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We
+    // explicitly specify the target address here to work around this problem.
+    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+    if (socket_ops::listen(acceptor.get(),
+          SOMAXCONN, ec) == socket_error_retval)
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    socket_holder client(socket_ops::socket(
+          AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+    if (client.get() == invalid_socket)
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
+          addr_len, ec) == socket_error_retval)
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
+    if (server.get() == invalid_socket)
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+    
+    ioctl_arg_type non_blocking = 1;
+    if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking, ec))
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    opt = 1;
+    socket_ops::setsockopt(client.get(),
+        IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+    non_blocking = 1;
+    if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking, ec))
+    {
+      asio::system_error e(ec, "socket_select_interrupter");
+      boost::throw_exception(e);
+    }
+
+    opt = 1;
+    socket_ops::setsockopt(server.get(),
+        IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+    read_descriptor_ = server.release();
+    write_descriptor_ = client.release();
+  }
+
+  // Destructor.
+  ~socket_select_interrupter()
+  {
+    asio::error_code ec;
+    if (read_descriptor_ != invalid_socket)
+      socket_ops::close(read_descriptor_, ec);
+    if (write_descriptor_ != invalid_socket)
+      socket_ops::close(write_descriptor_, ec);
+  }
+
+  // Interrupt the select call.
+  void interrupt()
+  {
+    char byte = 0;
+    socket_ops::buf b;
+    socket_ops::init_buf(b, &byte, 1);
+    asio::error_code ec;
+    socket_ops::send(write_descriptor_, &b, 1, 0, ec);
+  }
+
+  // Reset the select interrupt. Returns true if the call was interrupted.
+  bool reset()
+  {
+    char data[1024];
+    socket_ops::buf b;
+    socket_ops::init_buf(b, data, sizeof(data));
+    asio::error_code ec;
+    int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
+    bool was_interrupted = (bytes_read > 0);
+    while (bytes_read == sizeof(data))
+      bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
+    return was_interrupted;
+  }
+
+  // Get the read descriptor to be passed to select.
+  socket_type read_descriptor() const
+  {
+    return read_descriptor_;
+  }
+
+private:
+  // The read end of a connection used to interrupt the select call. This file
+  // descriptor is passed to select such that when it is time to stop, a single
+  // byte will be written on the other end of the connection and this
+  // descriptor will become readable.
+  socket_type read_descriptor_;
+
+  // The write end of a connection used to interrupt the select call. A single
+  // byte may be written to this to wake up the select which is waiting for the
+  // other end to become readable.
+  socket_type write_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP

+ 216 - 0
ext/asio/asio/detail/socket_types.hpp

@@ -0,0 +1,216 @@
+//
+// socket_types.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2010 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_SOCKET_TYPES_HPP
+#define ASIO_DETAIL_SOCKET_TYPES_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/config.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
+#  error WinSock.h has already been included
+# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
+# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+#  if defined(_MSC_VER) || defined(__BORLANDC__)
+#   pragma message( \
+  "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\
+  "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\
+  "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\
+  "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).")
+#  else // defined(_MSC_VER) || defined(__BORLANDC__)
+#   warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.
+#   warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line.
+#   warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
+#  endif // defined(_MSC_VER) || defined(__BORLANDC__)
+#  define _WIN32_WINNT 0x0501
+# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+# if defined(_MSC_VER)
+#  if defined(_WIN32) && !defined(WIN32)
+#   if !defined(_WINSOCK2API_)
+#    define WIN32 // Needed for correct types in winsock2.h
+#   else // !defined(_WINSOCK2API_)
+#    error Please define the macro WIN32 in your compiler options
+#   endif // !defined(_WINSOCK2API_)
+#  endif // defined(_WIN32) && !defined(WIN32)
+# endif // defined(_MSC_VER)
+# if defined(__BORLANDC__)
+#  include <stdlib.h> // Needed for __errno
+#  if defined(__WIN32__) && !defined(WIN32)
+#   if !defined(_WINSOCK2API_)
+#    define WIN32 // Needed for correct types in winsock2.h
+#   else // !defined(_WINSOCK2API_)
+#    error Please define the macro WIN32 in your compiler options
+#   endif // !defined(_WINSOCK2API_)
+#  endif // defined(__WIN32__) && !defined(WIN32)
+#  if !defined(_WSPIAPI_H_)
+#   define _WSPIAPI_H_
+#   define ASIO_WSPIAPI_H_DEFINED
+#  endif // !defined(_WSPIAPI_H_)
+# endif // defined(__BORLANDC__)
+# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
+#  if !defined(WIN32_LEAN_AND_MEAN)
+#   define WIN32_LEAN_AND_MEAN
+#  endif // !defined(WIN32_LEAN_AND_MEAN)
+# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
+# if !defined(ASIO_NO_NOMINMAX)
+#  if !defined(NOMINMAX)
+#   define NOMINMAX 1
+#  endif // !defined(NOMINMAX)
+# endif // !defined(ASIO_NO_NOMINMAX)
+# if defined(__CYGWIN__)
+#  if !defined(__USE_W32_SOCKETS)
+#   error You must add -D__USE_W32_SOCKETS to your compiler options.
+#  endif // !defined(__USE_W32_SOCKETS)
+# endif // defined(__CYGWIN__)
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <mswsock.h>
+# if defined(ASIO_WSPIAPI_H_DEFINED)
+#  undef _WSPIAPI_H_
+#  undef ASIO_WSPIAPI_H_DEFINED
+# endif // defined(ASIO_WSPIAPI_H_DEFINED)
+# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
+#  if defined(UNDER_CE)
+#   pragma comment(lib, "ws2.lib")
+#  elif defined(_MSC_VER) || defined(__BORLANDC__)
+#   pragma comment(lib, "ws2_32.lib")
+#   pragma comment(lib, "mswsock.lib")
+#  endif // defined(_MSC_VER) || defined(__BORLANDC__)
+# endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
+# include "asio/detail/old_win_sdk_compat.hpp"
+#else
+# include <sys/ioctl.h>
+# include <sys/poll.h>
+# include <sys/types.h>
+# if defined(__hpux) && !defined(__HP_aCC)
+#  include <sys/time.h>
+# else
+#  include <sys/select.h>
+# endif
+# include <sys/socket.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+# include <net/if.h>
+# include <limits.h>
+# if defined(__sun)
+#  include <sys/filio.h>
+#  include <sys/sockio.h>
+# endif
+#endif
+#include "asio/detail/pop_options.hpp"
+
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef SOCKET socket_type;
+const SOCKET invalid_socket = INVALID_SOCKET;
+const int socket_error_retval = SOCKET_ERROR;
+const int max_addr_v4_str_len = 256;
+const int max_addr_v6_str_len = 256;
+typedef sockaddr socket_addr_type;
+typedef in_addr in4_addr_type;
+typedef ip_mreq in4_mreq_type;
+typedef sockaddr_in sockaddr_in4_type;
+# if defined(ASIO_HAS_OLD_WIN_SDK)
+typedef in6_addr_emulation in6_addr_type;
+typedef ipv6_mreq_emulation in6_mreq_type;
+typedef sockaddr_in6_emulation sockaddr_in6_type;
+typedef sockaddr_storage_emulation sockaddr_storage_type;
+typedef addrinfo_emulation addrinfo_type;
+# else
+typedef in6_addr in6_addr_type;
+typedef ipv6_mreq in6_mreq_type;
+typedef sockaddr_in6 sockaddr_in6_type;
+typedef sockaddr_storage sockaddr_storage_type;
+typedef addrinfo addrinfo_type;
+# endif
+typedef unsigned long ioctl_arg_type;
+typedef u_long u_long_type;
+typedef u_short u_short_type;
+const int shutdown_receive = SD_RECEIVE;
+const int shutdown_send = SD_SEND;
+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;
+# if defined (_WIN32_WINNT)
+const int max_iov_len = 64;
+# else
+const int max_iov_len = 16;
+# endif
+#else
+typedef int socket_type;
+const int invalid_socket = -1;
+const int socket_error_retval = -1;
+const int max_addr_v4_str_len = INET_ADDRSTRLEN;
+#if defined(INET6_ADDRSTRLEN)
+const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
+#else // defined(INET6_ADDRSTRLEN)
+const int max_addr_v6_str_len = 256;
+#endif // defined(INET6_ADDRSTRLEN)
+typedef sockaddr socket_addr_type;
+typedef in_addr in4_addr_type;
+# if defined(__hpux)
+// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined.
+struct in4_mreq_type
+{
+  struct in_addr imr_multiaddr;
+  struct in_addr imr_interface;
+};
+# else
+typedef ip_mreq in4_mreq_type;
+# endif
+typedef sockaddr_in sockaddr_in4_type;
+typedef in6_addr in6_addr_type;
+typedef ipv6_mreq in6_mreq_type;
+typedef sockaddr_in6 sockaddr_in6_type;
+typedef sockaddr_storage sockaddr_storage_type;
+typedef sockaddr_un sockaddr_un_type;
+typedef addrinfo addrinfo_type;
+typedef int ioctl_arg_type;
+typedef uint32_t u_long_type;
+typedef uint16_t u_short_type;
+const int shutdown_receive = SHUT_RD;
+const int shutdown_send = SHUT_WR;
+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;
+# if defined(IOV_MAX)
+const int max_iov_len = IOV_MAX;
+# else
+// POSIX platforms are not required to define IOV_MAX.
+const int max_iov_len = 16;
+# endif
+#endif
+const int custom_socket_option_level = 0xA5100000;
+const int enable_connection_aborted_option = 1;
+const int always_fail_option = 2;
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SOCKET_TYPES_HPP

+ 0 - 0
ext/asio/asio/detail/solaris_fenced_block.hpp


Some files were not shown because too many files changed in this diff