Coder Social home page Coder Social logo

asio's People

Contributors

andrei-datcu avatar chriskohlhoff avatar ennui93 avatar ewienik avatar gjasny avatar gummif avatar inetic avatar jackburton79 avatar jcelerier avatar klemens-morgenstern avatar marcelraad avatar matthewtff avatar melroy89 avatar miguelcompany avatar nickg avatar nomis avatar palebedev avatar petrhosek avatar ramirisu avatar reddwarf69 avatar regular384 avatar rpavlik avatar saltfishami avatar schra avatar sconrad450 avatar stephencwills avatar tanzislam avatar tusikalanse avatar vinipsmaker avatar xavier2k6 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

asio's Issues

Standalone Asio `deadline_timer` depends on `boost::posix_time`

In attempting to port via-httplib to use standalone asio I was unable to remove all dependencies on the boost library because of deadline_timer and basic_deadline_timer:

typedef basic_deadline_timer< boost::posix_time::ptime > deadline_timer;

I expected to be able to use the following instead:

typedef basic_deadline_timer< std::chrono::ptime > deadline_timer;

However, this would not compile because Standalone Asio basic_deadline_timer.hpp tests the macro ASIO_HAS_BOOST_DATE_TIME just after the include guards...

Documentation is not clear if boost::asio::spawn can be used with multiple threads

I have been testing out boost::asio::spawn that results in a boost::asio::yield_context and it appears that if I have more than one thread in the thread pool for io_service it will eventually result in an access violation. This is being caused by io_service resuming the coroutine from a different thread. From what I have read this is correct behavior, however the documentation on spawn and yield_context do not mention the thread safety problem. It would be very helpful if the documentation discussed this issue in more detail to prevent this misunderstanding.

Update Services examples to use basic_io_object class

Hi,

I am trying to create a custom io service, and I am looking for best practice examples.

The "Services" example implements an io service for logging, but it does not use the basic_io_object class as base class for the I/O object (class basic_logger). Is there a good reason to not use this base class ?

Thank!

There should be a way to non-destructively disassociate a native handle from a basic_socket

I'm working with a somewhat complex system and trying to re-write one subsystem to use ASIO without rewriting other subsystem, yet. The subsystem under re-write does not open connections: that is handled by a separate connection pooling subsystem. This is no problem when constructing a stream_socket, because of the stream socket constructor that consumes a native_handle_type, so I can just use the descriptor that I get back from the pool subsystem.

However, after the re-written subsystem has completed its activity, it is expected to hand back the still open socket to the pooling subsystem. This requires that I sever the connection between the stream_socket object and the native handle, so that when the stream_socket object is destroyed, the handle remains valid.

I cannot see a way to accomplish this in ASIO as of the ASIO 1-11-0 API. The ability to temporarily and non-destructively associate existing sockets with ASIO types would make it much easier to incrementally integrate ASIO with existing network libraries while migrating fully to ASIO.

Apologies if I have overlooked a mechanism for doing this in the existing code.

ASIO_HAS_STD_ADDRESSOF not set for Visual Studio

Both VC10 and VC11 support std::addressof(). However, this is not detected by ASIO in addressof.hpp, resulting in the Boost file "boost/utility/addressof.hpp" being included, despite ASIO_STANDALONE being defined.

spawn() in boost trunk

There are multiple problems with spawn() in asio with boost 1.55 and trunk

  • spawn.hpp uses defined(BOOST_COROUTINES_UNIDRECT) as a condition, which is a typo, it should be defined(BOOST_COROUTINES_UNIDIRECT) (note that boost trunk no longer even has the old coroutine API)
  • spawn() doesn't work with coroutines v2, and the reason is that it uses push_coroutine<void> for callee_type

The reason push_coroutine<void> doesn't work for callee_type is that there's no context switch on coroutine construction (since push_coroutine expects a value and there's no value until after coroutine is constructed and said value is assigned). So context switch only happens on the line with (*coro)();, and then coroutine runs until ca(); // Yield until coroutine pointer has been initialised. and there's no longer a way for it to continue.

So it seems that you would either need to make callee_type a pull_coroutine<void>, or make use of the fact push_coroutine<void> doesn't context switch on construction, making it quite a bit simpler and better performing:

Index: impl/spawn.hpp
===================================================================
--- impl/spawn.hpp  (revision 86799)
+++ impl/spawn.hpp  (working copy)
@@ -242,7 +242,9 @@
     void operator()(typename basic_yield_context<Handler>::caller_type& ca)
     {
       shared_ptr<spawn_data<Handler, Function> > data(data_);
+#if !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)
       ca(); // Yield until coroutine pointer has been initialised.
+#endif
       const basic_yield_context<Handler> yield(
           data->coro_, ca, data->handler_);
       (data->function_)(yield);
Index: spawn.hpp
===================================================================
--- spawn.hpp   (revision 86799)
+++ spawn.hpp   (working copy)
@@ -58,7 +58,7 @@
    */
 #if defined(GENERATING_DOCUMENTATION)
   typedef implementation_defined callee_type;
-#elif defined(BOOST_COROUTINES_UNIDRECT) || defined(BOOST_COROUTINES_V2)
+#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)
   typedef boost::coroutines::push_coroutine<void> callee_type;
 #else
   typedef boost::coroutines::coroutine<void()> callee_type;
@@ -73,7 +73,7 @@
    */
 #if defined(GENERATING_DOCUMENTATION)
   typedef implementation_defined caller_type;
-#elif defined(BOOST_COROUTINES_UNIDRECT) || defined(BOOST_COROUTINES_V2)
+#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)
   typedef boost::coroutines::pull_coroutine<void> caller_type;
 #else
   typedef boost::coroutines::coroutine<void()>::caller_type caller_type;

Broken support for older g++ version

Latest version of asio depends on C++11 feature std::addressof or forces developers to use Boost. C++11 is not supported in older compilers (like g++ 3.2.2). With this dependency I am unable to use asio on mature projects.

I did not found any remark to this dependency or drop of compiler support. Is there an older version which provides support for C++98 and C++03 only compilers?

Several compile problems with dev_poll_reactor on Solaris

This issue was discovered on 1-11-0, but it is still broken on master. There appear to be several problems in the dev_poll_reactor.ipp file:

  • On dev_poll_reactor.ipp:33, the wrong base class is used when invoking the base class constructor.
  • There appears to be a merge marker at line 70
  • Removing the merge marker and the file still fails to compile at line 72 because the fork_helper should no longer exist
  • Removing the fork_helper seems to get it compiling
-bash-4.2$ uname -a
SunOS ip-10-169-64-240.ec2.internal 5.11 omnios-d3950d8 i86pc i386 i86xpv

-bash-4.2$ git describe --tags
asio-1-11-0-36-g5bb7a74

-bash-4.2$ ./autogen.sh
Running aclocal ...
main::scan_file() called too early to check prototype at /usr/bin/aclocal line 642.
Running autoconf ...
Running automake --add-missing --foreign ...
configure.ac:7: installing './compile'
configure.ac:6: installing './config.guess'
configure.ac:6: installing './config.sub'
configure.ac:4: installing './install-sh'
configure.ac:4: installing './missing'
src/examples/cpp03/Makefile.am: installing './depcomp'

-bash-4.2$ /opt/toolchain/bin/g++ --version
g++ (GCC) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

-bash-4.2$ ./configure --prefix=/data/opt --without-boost --enable-separate-compilation CC=/opt/toolchain/bin/gcc CXX=/opt/toolchain/bin/g++
checking whether to enable maintainer-specific portions of Makefiles... no
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking how to create a ustar tar archive... gnutar
checking build system type... i386-pc-solaris2.11
checking host system type... i386-pc-solaris2.11
checking for style of include used by make... GNU
checking for gcc... /opt/toolchain/bin/gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether /opt/toolchain/bin/gcc accepts -g... yes
checking for /opt/toolchain/bin/gcc option to accept ISO C89... none needed
checking dependency style of /opt/toolchain/bin/gcc... gcc3
checking whether /opt/toolchain/bin/gcc and cc understand -c and -o together... yes
checking whether we are using the GNU C++ compiler... yes
checking whether /opt/toolchain/bin/g++ accepts -g... yes
checking dependency style of /opt/toolchain/bin/g++... gcc3
checking for ranlib... ranlib
checking openssl/ssl.h usability... yes
checking openssl/ssl.h presence... no
configure: WARNING: openssl/ssl.h: accepted by the compiler, rejected by the preprocessor!
configure: WARNING: openssl/ssl.h: proceeding with the compiler's result
checking for openssl/ssl.h... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating include/Makefile
config.status: creating src/Makefile
config.status: creating src/tests/Makefile
config.status: creating src/examples/cpp03/Makefile
config.status: creating src/examples/cpp11/Makefile
config.status: creating src/examples/cpp14/Makefile
config.status: executing depfiles commands

-bash-4.2$ make all
Making all in include
Making all in src
Making all in examples/cpp11
depbase=`echo ../../asio.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
/opt/toolchain/bin/g++ -DPACKAGE_NAME=\"asio\" -DPACKAGE_TARNAME=\"asio\" -DPACKAGE_VERSION=\"1.11.0\" -DPACKAGE_STRING=\"asio\ 1.11.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"asio\" -DVERSION=\"1.11.0\" -D_REENTRANT=1 -I.    -std=c++0x  -DASIO_STANDALONE -DASIO_SEPARATE_COMPILATION -I./../../../include -g -O2 -D_PTHREADS -ftemplate-depth-256 -MT ../../asio.o -MD -MP -MF $depbase.Tpo -c -o ../../asio.o ../../asio.cpp &&\
mv -f $depbase.Tpo $depbase.Po
In file included from ./../../../include/asio/impl/src.hpp:33:0,
                 from ../../asio.cpp:11:
./../../../include/asio/detail/impl/dev_poll_reactor.ipp: In constructor ‘asio::detail::dev_poll_reactor::dev_poll_reactor(asio::execution_context&)’:
./../../../include/asio/detail/impl/dev_poll_reactor.ipp:33:19: error: type ‘asio::detail::service_base<asio::detail::dev_poll_reactor>’ is not a direct base of ‘asio::detail::dev_poll_reactor’
   : asio::detail::service_base<dev_poll_reactor>(ctx),
                   ^
./../../../include/asio/detail/impl/dev_poll_reactor.ipp:38:20: error: no matching function for call to ‘asio::detail::execution_context_service_base<asio::detail::dev_poll_reactor>::execution_context_service_base()’
     shutdown_(false)
                    ^
./../../../include/asio/detail/impl/dev_poll_reactor.ipp:38:20: note: candidate is:
In file included from ./../../../include/asio/impl/execution_context.ipp:19:0,
                 from ./../../../include/asio/impl/src.hpp:24,
                 from ../../asio.cpp:11:
./../../../include/asio/execution_context.hpp:392:3: note: asio::detail::execution_context_service_base<Type>::execution_context_service_base(asio::execution_context&) [with Type = asio::detail::dev_poll_reactor]
   execution_context_service_base(execution_context& e)
   ^
./../../../include/asio/execution_context.hpp:392:3: note:   candidate expects 1 argument, 0 provided
In file included from ./../../../include/asio/impl/src.hpp:33:0,
                 from ../../asio.cpp:11:
./../../../include/asio/detail/impl/dev_poll_reactor.ipp: At global scope:
./../../../include/asio/detail/impl/dev_poll_reactor.ipp:70:1: error: expected unqualified-id before ‘<<’ token
 <<<<<<< HEAD
 ^
In file included from ./../../../include/asio/detail/impl/dev_poll_reactor.ipp:448:0,
                 from ./../../../include/asio/impl/src.hpp:33,
                 from ../../asio.cpp:11:
./../../../include/asio/detail/pop_options.hpp:67:29: error: expected ‘}’ before end of line
 #  pragma GCC visibility pop
                             ^
./../../../include/asio/detail/pop_options.hpp:67:29: error: expected ‘}’ before end of line
./../../../include/asio/detail/pop_options.hpp:67:29: error: expected declaration before end of line
*** Error code 1
make: Fatal error: Command failed for target `../../asio.o'
Current working directory /data/acm/asio/asio/src/examples/cpp11
*** Error code 1
The following command caused the error:
fail= failcom='exit 1'; \
for f in x $MAKEFLAGS; do \
  case $f in \
    *=* | --[!k]*);; \
    *k*) failcom='fail=yes';; \
  esac; \
done; \
dot_seen=no; \
target=`echo all-recursive | sed s/-recursive//`; \
list='examples/cpp11 tests'; for subdir in $list; do \
  echo "Making $target in $subdir"; \
  if test "$subdir" = "."; then \
    dot_seen=yes; \
    local_target="$target-am"; \
  else \
    local_target="$target"; \
  fi; \
  (CDPATH="${ZSH_VERSION+.}:" && cd $subdir && make  $local_target) \
  || eval $failcom; \
done; \
if test "$dot_seen" = "no"; then \
  make  "$target-am" || exit 1; \
fi; test -z "$fail"
make: Fatal error: Command failed for target `all-recursive'
Current working directory /data/acm/asio/asio/src
*** Error code 1
The following command caused the error:
fail= failcom='exit 1'; \
for f in x $MAKEFLAGS; do \
  case $f in \
    *=* | --[!k]*);; \
    *k*) failcom='fail=yes';; \
  esac; \
done; \
dot_seen=no; \
target=`echo all-recursive | sed s/-recursive//`; \
list='include src'; for subdir in $list; do \
  echo "Making $target in $subdir"; \
  if test "$subdir" = "."; then \
    dot_seen=yes; \
    local_target="$target-am"; \
  else \
    local_target="$target"; \
  fi; \
  (CDPATH="${ZSH_VERSION+.}:" && cd $subdir && make  $local_target) \
  || eval $failcom; \
done; \
if test "$dot_seen" = "no"; then \
  make  "$target-am" || exit 1; \
fi; test -z "$fail"
make: Fatal error: Command failed for target `all-recursive'

in need a way of polling events but not executing handlers

on some GUI programs, it's rather handy to have network IO and gui executed in the same thread.

way1

what if asio can provicde a way to "wait" for events but does not execute the handlers?say "asio::io_service::wait_events() will block until at least one handlers is ready to dispatch" and that thread can post mesage back to GUI loop, and have the GUI thread to do the dispatch job. thus, the handlers are all executed in GUI thread. no need to be careful to avoid multi-threaded GUI access.

// thread asio loop

void asio_loop( asio::io_service & io)
{
  while(!io.stoped())
  {
      io.wait_events();

     // call PostMessage , then let the GUI loop to execute  io.poll()
     // or call QCoreApplication::sendEvent() then let the GUI loop thread to execute  io.poll()
     // or call g_main_idle_add() to post an execution of io.poll()
     // or just signal an eventfd, then let the GUI loop thread to execute  io.poll()

 ///

   }

}


// now here is normal gui thread
void gui_lop()
{
  // normal GetMessage loop
  // or just  QApplication::exec()
  // or just  g_main_loop_run()
  // or  gtk_main()
 //  .....
}


way2

provide native_handle() for IOCP or epoll fd . so we can "wait" for asio related events in other message loop that provide the ability to monitor HANDLE or fd.

say


HANDLE iocphandle= asio::use_service<win_iocp_service>(io).native_handle();

MsgWaitForMultipleObjectsEx(1, & iocphandle,  -1, 0 ,0);

// and based on the return value
// call normal msg loop 
// call asio loop


fd epoll_fd =  asio::use_service<task_io_service>(io).native_handle();

// use epoll_fd to intergrate with glib/qt/libevent/ what ever event loop that can monitor an fd.

I don't even know which way is more cleaner or mo powerfull.

asio::async_connect reports success on failure

if you compile asio/src/examples/cpp11/chat/chat_client.cpp and point it at a host and port that doesn't exist or refuses the connection, instead of coming back with an error, such as host not found or connection refused, the error_code reports success (on the conversion to bool). (you might want to embellish the example with a std::cout << ec.message() << std::endl;)

This appears to be the case across Linux, Darwin, iOS and Android

synchronous connect seems to work correctly (i.e., echo/blocking_tcp_echo_client.cpp)

BOOST_WORKAROUND macro in buffer.hpp undefined

Line 52 of buffer.hpp generates an error:

if BOOST_WORKAROUND(BORLANDC, BOOST_TESTED_AT(0x582))
|| BOOST_WORKAROUND(SUNPRO_CC, BOOST_TESTED_AT(0x590))
define ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND
endif // BOOST_WORKAROUND(__BORLANDC
, BOOST_TESTED_AT(0x582))
// || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))

compile error about std::move

MSVC 2015 RC
asio 1.10.6

Following code is ok:
  auto data = std::make_unique<std::string>("abc");
  auto buffer = asio::buffer(data->c_str(), data->size());
  std::shared_ptr<std::string> data2 = std::move(data);
  asio::async_write(s, buffer,
    [data2](const asio::error_code&,  size_t) { ...  });

But the following code can not be compiled:
  auto data = std::make_unique<std::string>("abc");
  auto buffer = asio::buffer(data->c_str(), data->size());
  // data2 is unique_ptr<string>
  asio::async_write(s, buffer,
    [data2 = std::move(data)](const asio::error_code& error,
      size_t byte_transferred) { ... });

Why I can not capture a unique_ptr here?
It's seems the handler object must be copyable?

segfault when `handler` called before `result.get()`

If the following async_foobar is available:

template<class CompletionToken>
typename asio::async_result<
    typename asio::handler_type<CompletionToken,
                                void(system::error_code)>::type>::type
async_foobar(CompletionToken &&token)
{
    typedef typename asio::handler_type<
        CompletionToken, void(system::error_code)>::type Handler;

    Handler handler(std::forward<CompletionToken>(token));
    asio::async_result<Handler> result(handler);

    // handler not scheduled (i.e. called before `result.get()`)
    handler(system::error_code());
    return result.get();
}

And called within the following context:

#include <cstdlib>

#include <boost/asio/io_service.hpp>
#include <boost/asio/spawn.hpp>

using namespace std;
using namespace boost;

int main(int argc, char *argv[])
{
    asio::io_service ios;

    auto work = [](asio::yield_context yield) {
        while (true) {
            try {
                async_foobar(yield);
            } catch (std::exception &e) {
                cerr << "Aborting on exception: " << e.what() << endl;
                std::exit(1);
            }
        };
    };

    spawn(ios, work);
    ios.run();
    return 0;
}

The program will segfault (not even an exception is throw or anything). The debug output follows:

vinipsmaker ~ $ clang++ test.cpp -std=c++11 -lboost_system -lboost_coroutine -g
vinipsmaker ~ $ gdb a.out 
GNU gdb (GDB) 7.8
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...done.
(gdb) run
Starting program: /home/vinipsmaker/a.out 
Got object file from memory but can't read symbols: File truncated.
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ff7d48 in ?? ()
(gdb) backtrace
#0  0x00007ffff7ff7d48 in ?? ()
#1  0x00007ffff7ff7d48 in ?? ()
#2  0x00007fffffffe548 in ?? ()
#3  0x00007ffff7ff7da0 in ?? ()
#4  0x0000000000406383 in boost::asio::detail::coro_entry_point<boost::asio::detail::wrapped_handler<boost::asio::io_service::strand, void (*)(), boost::asio::detail::is_continuation_if_running>, main::$_0&>::operator()(boost::coroutines::coroutine<void (), 0>&) (this=0x7ffff7ff7e70, ca=...)
    at /usr/include/boost/asio/impl/spawn.hpp:248
#5  0x000000000043cc00 in ?? ()
#6  0x00007ffff7ff7e70 in ?? ()
#7  0x000000000043c8c0 in ?? ()
#8  0x0000000000000000 in ?? ()
(gdb) frame 4
#4  0x0000000000406383 in boost::asio::detail::coro_entry_point<boost::asio::detail::wrapped_handler<boost::asio::io_service::strand, void (*)(), boost::asio::detail::is_continuation_if_running>, main::$_0&>::operator()(boost::coroutines::coroutine<void (), 0>&) (this=0x7ffff7ff7e70, ca=...)
    at /usr/include/boost/asio/impl/spawn.hpp:248
248           (data->function_)(yield);
(gdb) l
243         {
244           shared_ptr<spawn_data<Handler, Function> > data(data_);
245           ca(); // Yield until coroutine pointer has been initialised.
246           const basic_yield_context<Handler> yield(
247               data->coro_, ca, data->handler_);
248           (data->function_)(yield);
249           if (data->call_handler_)
250             (data->handler_)();
251         }
252

(Feature request) Add support for Windows SChannel based SSL/TLS

The current ASIO library supports OpenSSL based ssl channels which is useful for Linux and Mac OSX software as the library is included by the operating system, however for Windows OpenSSL is not included by default and instead the application is required to distribute the library itself. The problem with this arrangement is that the distributor of the software is required to keep the OpenSSL library up to date as vulnerabilities are discovered. As has been proven recently this can happen pretty often. It is unrealistic for a business to have to update this library rather than having Windows Update automatically force the update. Allowing the use of the built in SChannel support in Windows would solve this problem. How difficult would this be to accomplish? I am willing to help with the development but my time is fairly limited and I am not sure how big an undertaking this would be.

Movable Timers

The deadline timers are not movable, if this is not on purpose it would be great if timers were movable :)

Marking things as deprecated

It's getting more & more difficult to see what's deprecated in asio without constantly referring to the docs or even git logs and I shouldn't need to that for existing code. I only notice because I was trying to follow progress with the standard proposal.

Could you please mark things as deprecated so that the compiler/IDE tells me when I'm using something that's deprecated.

In C++14 we can put [[deprecated("use X instead")]] but you could wrap it in a macro to fall back to GCC's __attribute__((deprecated)) or MSVC's declspec(deprecated).

Yes this will introduce a lot of compiler noise to those upgrading, but that's kind of the point. People should be discouraged from using deprecated APIs.

Defining ASIO_NO_DEPRECATED is an option, but it's nicer to be able to just have warnings so it can be gradually fixed.

Mingw broken by recent commit

Just last few days getting this with master branch with mingw, GCC 4.9.1. I assume some recent commit has broken things:

In file included from asio/asio/include/asio/datagram_socket_service.hpp:28:0,
                 from asio/asio/include/asio/basic_datagram_socket.hpp:21,
                 from asio/asio/include/asio.hpp:21,
                 from include/boost/afio/bindlib/bind/stl1z/asio/networking:5,
                 from include/boost/afio/config.hpp:258,
                 from include/boost/afio/afio.hpp:41,
                 from test/test_functions.hpp:17,
                 from test/test_all.cpp:4:
asio/asio/include/asio/detail/win_iocp_socket_service.hpp: In member function 'typename Protocol::socket asio::detail::win_iocp_socket_service<Protocol>::accept(asio::detail::win_iocp_socket_service<Protocol>::implementation_type&, asio::io_service*, asio::detail::win_iocp_socket_service<Protocol>::endpoint_type*, asio::error_code&)':
asio/asio/include/asio/detail/win_iocp_socket_service.hpp:466:61: error: there are no arguments to 'get_io_service' that depend on a template parameter, so a declaration of 'get_io_service' must be available [-fpermissive]
         peer_io_service ? *peer_io_service : get_io_service());
                                                             ^
asio/asio/include/asio/detail/win_iocp_socket_service.hpp:466:61: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)

"Default constructor." is insufficient documentation

I'm looking specifically at ip::basic_endpoint and ip::address, which can be constructed from existing values (in which case it's pretty clear what the object's state will be after construction) but also provide default constructors. While it's interesting to know that these classes have default constructors, the minimalist documentation "Default constructor." (example) leaves a lot of questions unanswered.

For ip::address, will the default constructor construct a special "nil" object or will it construct an actual IPv4 equivalent to "0.0.0.0" or IPv6 "::"? Will a default-constructed object return true for is_unspecified()? What kind of values does is_unspecified() deem as "unspecified" - nil, "0.0.0.0", "::", and/or all of them? Will a default-constructed object convert to a string successfully or throw an exception, or return an empty string? What sort of exception or error code value can I expect from to_string() when things go wrong?

For ip::endpoint, does it initialize with a default-constructed ip::address object or with a default IPv4/IPv6 address? Is the port initialized with 0 or left to random C++ default allocation? Am I supposed to check for an unspecified address when determining whether the endpoint has been initialized with a given value, should I include the port value in such a check or not rely on its value at all after default construction?

Some of these questions can be trivially answered by looking at the code, others require ploughing through macros defined by other macros nested in yet more macros. I should be able to answer all of them just by looking at the documentation. This is not the case today, I hope it can be fixed.

Thanks,
Jakob

socket::available() returns wrong value on FreeBSD

FreeBSD's FIONREAD ioctl returns a value which includes the IP header, so the true value of bytes available to be read is:

#ifdef __FreeBSD__
    // FreeBSD's FIONREAD when asked of a UDP socket includes the UDP and IP headers which
    // for IPv4 is 16 bytes and for IPv6 is 24 bytes
    datagram_size -= remote_endpoint.address().is_v6() ? 24 : 16;
#endif

Asio hangs on system call close (Mac OS X)

This test:

#include <thread>
#include <asio.hpp>
#include <boost/chrono.hpp>

int main() {
  for (int i = 0; i < 10000; ++i) {
    std::cout << i << std::endl;

    asio::io_service ioService;
    asio::deadline_timer timer(ioService);

    ioService.post([&](){
      timer.expires_from_now(boost::posix_time::milliseconds(1));
      timer.async_wait([&](const asio::error_code &) {});
    });

    ioService.post([&](){
      ioService.post([](){});
    });

    // Run some threads
    std::vector<std::thread> threads;
    for (auto i=0; i<3; ++i) {
      threads.emplace_back([&](){ ioService.run(); });
    }
    for (auto& i: threads) {
      i.join();
    }
  }
  return EXIT_SUCCESS;
}

hangs on system call close:

Tested on: Mac OS X 10.9.1/10.8.5, clang -stdlib=libc++ -std=c++11, boost 1.55.0
master branch: e80030f
cpp11-only branch: f1cbf4f

Originally from: http://stackoverflow.com/questions/21835749/boost-asio-io-service-destructor-hangs-on-os-x

Bug leading to false report of SSL error on async_shutdown

In asio/ssl/detail/io.hpp, the io_op class has a subtle bug that leads async_shutdown to falsely report a SHORT_READ error. I'm using the source code from the latest master (18 December 2014).

The following code is called when a deadline timer is cancelled, and the value of bytes_transferred is very large ~size_t(0). The core_.input_ buffer is set to 17K of junk, and then this junk is passed as input to the core_.engine_.

        switch (want_)
        {
        case engine::want_input_and_retry:

          // Add received data to the engine's input.
          core_.input_ = asio::buffer(
              core_.input_buffer_, bytes_transferred);
          core_.input_ = core_.engine_.put_input(core_.input_);

Here is my fix:

diff --git a/asio/include/asio/ssl/detail/io.hpp b/asio/include/asio/ssl/detail/io.hpp
index 0916bea..dfc808b 100644
--- a/asio/include/asio/ssl/detail/io.hpp
+++ b/asio/include/asio/ssl/detail/io.hpp
@@ -220,8 +220,12 @@ public:
         }

         default:
-        if (bytes_transferred != ~std::size_t(0) && !ec_)
+        if (bytes_transferred == ~std::size_t(0)) {
+          // No data transferred when deadline_timer cancelled.
+          bytes_transferred = 0;
+        } else if (!ec_) { 
           ec_ = ec;
+        }

         switch (want_)
         {

Here is a more detailed trace of the handlers. In this setup, two connections (3 and 4) are connected via SSL, and there is no data "in the pipe".

  1. I invoke async_shutdown on connection 4. Connection 4 sends a "finished" SSL record. (ASIO handler 63 is unrelated to either connection)

    TCP_Connection::shutdown started {connid: 4}
    @asio|1418924613.982898|63*64|[email protected]_send
    @asio|1418924613.983189|<63|

  2. Connection 4 is done sending the "finished" SSL record. It awaits the reply.

    @asio|1418924613.983223|>64|ec=system:0,bytes_transferred=31
    @asio|1418924613.983264|64*67|[email protected]_wait
    @asio|1418924613.983286|<64|

  3. Connection 3 receives the "finished" SSL record and starts its own async_shutdown.

    @asio|1418924613.984085|>48|ec=system:0,bytes_transferred=31
    asyncReadHeader callback {connid: 3} {msg: End of file, err: 2}
    TCP_Connection::shutdown started {connid: 3}
    @asio|1418924613.984378|48*70|[email protected]_send
    @asio|1418924613.984457|<48|

  4. Connection 3 is done sending the "finished" SSL record. Connection 3's side of the async_shutdown completes successfully.

    @asio|1418924613.986886|>70|ec=system:0,bytes_transferred=31
    TCP_Connection::shutdown handler called {connid: 3}
    @asio|1418924613.987017|70|[email protected]
    @asio|1418924613.987087|<70|

  5. Connection 4 receives the "finished" SSL record. It cancels its timer.

    @asio|1418924613.988099|>60|ec=system:0,bytes_transferred=31
    @asio|1418924613.988127|60|[email protected]
    asyncReadHeader callback {connid: 4} {msg: End of file, err: 2}
    @asio|1418924613.988321|<60|

  6. Connection 4's timer handler is called. The large value of bytes_transferred leads to garbage data in the input buffer, causing the SHORT_READ shutdown error.

    @asio|1418924613.988514|>67|ec=asio.system:89
    TCP_Connection::shutdown handler called {connid: 4}
    TCP_Connection::shutdown result {connid: 4} {msg: SHORT_READ, err: 268435706}
    @asio|1418924613.988693|67|[email protected]
    @asio|1418924613.988767|<67|

ip multicast tests fail under pbuilder

The test suite (of the non-boost asio) fails under restricted environments, where setsockopt returns ENODEV when given the IP_ADD_MEMBERSHIP argument. This led to the following Debian bug report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=769306

The following patch tries to circumvent this by ignoring join failures due to ENODEV and makes the leave_group tests conditional on join_group success:
http://anonscm.debian.org/cgit/collab-maint/asio.git/plain/debian/patches/relax-ip-multicast-tests.diff

Thread choice

Greetings.

There seems to be a problem with how the thread implementation is chosen. In some cases, even though at least one type is possible, null_thread is selected. That will, of course, ruin everything.

Let's expose the important pieces. The first file is thread.hpp. The two big blocks have the same behavior : null_thread is always used (firstly included, secondly typedefed) when ASIO_HAS_THREADS is undefined. One could think that this is normal and that a lack of definition really means that there are no threads available. The rest of the blocks also give that impression because in case a definiton was found, it then proceeds to include the right files and typedef the right implementation. However, as it is now at least, ASIO_HAS_THREADS has little to do with the other implementations.

This is where the second file comes into play : config.hpp. This is where ASIO_HAS_THREADS is defined. Look at the conditions for yourself and compare them to those you can see in the blocks of the previous file.

In my case, the correct type would be std_thread (no boost, windows, posix/phtread for me). ASIO_HAS_STD_THREAD is correctly defined in config.hpp but it never has a chance to be used.

I believe the best fix would be to add this to the conditions in config.hpp :

#  elif defined(ASIO_HAS_STD_THREAD)
#   define ASIO_HAS_THREADS 1

It fixes the problem for my particular case. I don't know if it is the only case or not and I haven't tested further than that. I hope this can be of help. Thanks for your hard work in any case.

Signal handler example won't compile

I'm currently trying to add signal handling to an application that uses Asio without Boost. I tried to add a private method as my signal handler as explained at the bottom of this page but I get the following error when compiling:

error: no member named 'error' in namespace 'asio::placeholders'

I've checked the namespace and error does seem to be there although wrapped in an #if:

#if defined(GENERATING_DOCUMENTATION)

Also, I'm using std::bind instead of boost::bind.

ASIO G++/CLang++ warnings.

When building an application (Linux only, OSX & FreeBSD are fine) that utilises ASIO (Header only) with the following build arguments:

-Wall -Wextra -Weffc++ -pedantic

The terminal is bombarded with warnings all over the place. I've attempted to silence these warnings:

  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-W..."
  #pragma GCC diagnostric pop

And other assorted hacks, with no luck.

a) Are you aware of a work around?
b) Are you aware of these warnings and intend to address them?

select_reactor::run ignores error_code

In select_reactor.ipp, line 212, the outparam "ec" (error_code) of the socket_ops::select call is ignored.

If I understand the code correctly this can lead to a busy loop when one of the underlying sockets is damaged/invalid. We experienced high CPU usage in our application by one specific thread, especially when the process was idle for a long time or woke from hibernation. The callstack always lead to the select_reactor-Loop.

Some more information: our application makes a client connection to a partner process via async_connect. This internally opens three socket connections for the "self pipe trick" (to support cancellation of asynchronous connections). When I close one of the two "trick" sockets from outside (e. g. via TCPView) the thread wreaks havoc using up one core.

As far as I understand the "trick" sockets are only needed as long as the real connection is not established. If this is the case it would probably be better to clean them up when the connection is established.

kevent() call hangs on FreeBSD 9 and 10

The behavior is demonstrated by tests/unit/buffered_read_stream. This test hangs indefinitely on the kevent() call. The test completes successfully if kqueue is disabled.

The bug was introduced in commit 3f47354, "Fix occasional close() system call hang on MacOS" (via git bisect)

Backtrace:

#0  0x0000000801b330ea in kevent () from /lib/libc.so.7
#1  0x00000000004168b5 in asio::detail::kqueue_reactor::run (this=0x8024289b0, block=<optimized out>, ops=...)
    at ./../../include/asio/detail/impl/kqueue_reactor.ipp:346
#2  0x00000000004166cd in asio::detail::task_io_service::do_run_one (this=0x802425200, lock=..., this_thread=..., ec=...)
    at ./../../include/asio/detail/impl/task_io_service.ipp:355
#3  0x00000000004162f8 in asio::detail::task_io_service::run (this=0x802425200, ec=...)
    at ./../../include/asio/detail/impl/task_io_service.ipp:148
#4  0x0000000000408eea in run (this=<optimized out>, this=<optimized out>) at ./../../include/asio/impl/io_service.ipp:58
#5  test_async_operations () at unit/buffered_read_stream.cpp:270
...

Tested on FreeBSD 10.0-RELEASE #0 r260789, and some version of FreeBSD 9 (don't have access to that machine at the moment).

Intel C++ Compiler XE 12.1.x warnings

Environment:

  1. Windows 7 SP1 Pro.
  2. Intel C++ Compiler XE 12.1.5.344 build 20120612.
  3. Asio from Boost C++ Libraries 1.51.0.
  4. Warning level: Level4 (/W4).

Warnings:

1>..\..\..\..\boost_1_51_0\boost/asio/detail/impl/socket_ops.ipp(2787): warning #181: argument is incompatible with corresponding format string conversion
1>          sprintf(serv, "%u", ntohs(port));
1>                              ^
1>  
1>..\..\..\..\boost_1_51_0\boost/asio/detail/impl/socket_ops.ipp(2812): warning #181: argument is incompatible with corresponding format string conversion
1>            sprintf(serv, "%u", ntohs(port));
1>                                ^
1>
1>..\..\..\..\boost_1_51_0\boost/asio/detail/impl/win_static_mutex.ipp(48): warning #1786: function "swprintf(__wchar_t *, const __wchar_t *, ...)" (declared at line 85 of "c:\Program Files\Microsoft Visual Studio 10.0\VC\include\swprintf.inl") was declared deprecated ("swprintf has been changed to conform with the ISO C standard, adding an extra character count parameter. To use traditional Microsoft swprintf, set _CRT_NON_CONFORMING_SWPRINTFS.")
1>      swprintf(mutex_name,
1>      ^
1>   
1>..\..\..\..\boost_1_51_0\boost/asio/detail/winsock_init.hpp(78): warning #2415: variable "boost::asio::detail::winsock_init_instance" of static storage duration was declared but never referenced
1>    static const winsock_init<>& winsock_init_instance = winsock_init<>(false);
1>                                 ^
1>  
1>..\..\..\..\boost_1_51_0\boost/asio/error.hpp(244): warning #2415: variable "boost::asio::error::system_category" of static storage duration was declared but never referenced
1>    static const boost::system::error_category& system_category
1>                                                ^
1>  
1>..\..\..\..\boost_1_51_0\boost/asio/error.hpp(246): warning #2415: variable "boost::asio::error::netdb_category" of static storage duration was declared but never referenced
1>    static const boost::system::error_category& netdb_category
1>                                                ^
1>  
1>..\..\..\..\boost_1_51_0\boost/asio/error.hpp(248): warning #2415: variable "boost::asio::error::addrinfo_category" of static storage duration was declared but never referenced
1>    static const boost::system::error_category& addrinfo_category
1>                                                ^
1>  
1>..\..\..\..\boost_1_51_0\boost/asio/error.hpp(250): warning #2415: variable "boost::asio::error::misc_category" of static storage duration was declared but never referenced
1>    static const boost::system::error_category& misc_category
1>                                                ^
1>  
1>..\..\..\..\boost_1_51_0\boost/system/error_code.hpp(214): warning #2415: variable "boost::system::posix_category" of static storage duration was declared but never referenced
1>        static const error_category &  posix_category = generic_category();
1>                                       ^
1>  
1>..\..\..\..\boost_1_51_0\boost/system/error_code.hpp(215): warning #2415: variable "boost::system::errno_ecat" of static storage duration was declared but never referenced
1>        static const error_category &  errno_ecat     = generic_category();
1>                                       ^
1>  
1>..\..\..\..\boost_1_51_0\boost/system/error_code.hpp(216): warning #2415: variable "boost::system::native_ecat" of static storage duration was declared but never referenced
1>        static const error_category &  native_ecat    = system_category();
1>                                       ^

Proposed solution for warning #181:

--- boost/asio/detail/impl/socket_ops.ipp   Пн июл 23 15:03:31 2012
+++ boost/asio/detail/impl/socket_ops.ipp   Вс сен  2 15:55:52 2012
@@ -2782,9 +2782,9 @@
         return ec = boost::asio::error::no_buffer_space;
       }
 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
-      sprintf_s(serv, servlen, "%u", ntohs(port));
+      sprintf_s(serv, servlen, "%u", static_cast<unsigned>(ntohs(port)));
 #else
-      sprintf(serv, "%u", ntohs(port));
+      sprintf(serv, "%u", static_cast<unsigned>(ntohs(port)));
 #endif
     }
     else
@@ -2807,9 +2807,9 @@
           return ec = boost::asio::error::no_buffer_space;
         }
 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
-        sprintf_s(serv, servlen, "%u", ntohs(port));
+        sprintf_s(serv, servlen, "%u", static_cast<unsigned>(ntohs(port)));
 #else
-        sprintf(serv, "%u", ntohs(port));
+        sprintf(serv, "%u", static_cast<unsigned>(ntohs(port)));
 #endif
       }
 #if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) \

Flushing Serial Port

Is there a reason for not adding a way to flush serial port buffers? Searching on the internet, it seems like quite a few others also ran into a need for it as well and ended up resorting to platform specific hacks. It would be nice if the functionality is provided in asio.
Thanks!

For example:
http://stackoverflow.com/questions/22581315/how-to-discard-data-as-it-is-sent-with-boostasio
http://www.progtown.com/topic90228-how-for-boost-asio-serialport-to-make-flush.html
http://mnb.ociweb.com/mnb/MiddlewareNewsBrief-201303.html

Relax the requirements of Handlers to MoveConstructible

(See also https://svn.boost.org/trac/boost/ticket/8714)
(See also http://stackoverflow.com/questions/17211263)

The requirement that handlers be CopyConstructible doesn't allow for the following idiom:

void connection::send_response()
{
    // block until previous response is sent
    std::unique_lock<std::mutex> locker(response_mutex_);

    // prepare response
    response_ = "foo";

    // send response back to caller. move the unique_lock into the binder
    // to keep the mutex locked until asio is done sending.
    asio::async_write(stream_,
                      asio::const_buffers_1(response_.data(), response_.size()),
                      std::bind(&connection::response_sent, shared_from_this(),
                                _1, _2, std::move(locker))
                      );
}

void connection::response_sent(const boost::system::error_code& err, std::size_t len)
{
    if (err) handle_error(err);
    // the mutex is unlocked when the binder is destroyed
}

Please remove this restriction, there is no reason for it when using C++11.

Build asio in FreeBSD 8 Failure

Compiler messages:

Making all in include
Making all in src
depbase=`echo tests/performance/client.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`; g++ \
-DPACKAGE_NAME=\"asio\" -DPACKAGE_TARNAME=\"asio\" -DPACKAGE_VERSION=\"1.5.3\" \
-DPACKAGE_STRING=\"asio\ 1.5.3\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" \
-DPACKAGE=\"asio\" -DVERSION=\"1.5.3\" -D_REENTRANT=1 -DSTDC_HEADERS=1 \
-DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 \
-DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 \
-DHAVE_UNISTD_H=1 -I.    
-I/usr/local/include -I./../include -g -O2 -pthread -ftemplate-depth-256 \
-MT tests/performance/client.o -MD -MP -MF $depbase.Tpo \
-c -o tests/performance/client.o tests/performance/client.cpp && \
mv -f $depbase.Tpo $depbase.Po

tests/performance/client.cpp: In member function 'void session::start(asio::ip::basic_resolver_iterator)':
tests/performance/client.cpp:79: error: 'async_connect' is not a member of 'asio'
*** Error code 1

boost::asio::deadline_timer spawns a thread for each timer on Windows

My application uses lots of deadline_timers to provide timeout functionality for asynchronous operations. It appears that each deadline_timer spawns a thread to manage the wait on Windows. The threads don't complete once I call cancel on the timer. This leads to rapid resource exhaustion. On Windows the best way to implement the timers would be using "CreateTimerQueueTimer". The callback for the timer could then simply post the completion routines to the io_service. Using the flag WT_EXECUTEINTIMERTHREAD could potentially eliminate and performance penalties with the callback although I am not certain if it is legal given the design of asio on Windows. There is some discussion about the accuracy of this function but on windows it is nearly impossible to get timing resolution below ~15 ms using any method so I don't think that should be an issue. I am developing a work-around for my application and can send you the result if you are interested.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682485%28v=vs.85%29.aspx

How can i set Max Size Of Completion Event Queue?

First of all, I'm sorry about writing question as issue.

I Can't find proper place where i write question about asio.
There is a Similar question in StackOverflow, but is not properly answered.
StackOverflow

I have similar Question like above question in stackoverflow

If enqueuing Completion Event Queue by Asynchronous Operation Processor is more faster than dequeueing Completion Event Queue by by Proactor to Completion Handler, I think it will hit memory limit.
so. I have question how can i set max size of completion event queue? or how can i deal with this situation?

Incorrect behavior of io_service on IOCP

#include <boost/asio.hpp>
#include <iostream>

int main() {
    boost::asio::io_service ios;

    std::cout << "using Boost " << BOOST_LIB_VERSION << std::endl;

    ios.post([](){});   // add something
    ios.stop();         // Subsequent calls to run(), run_one(), poll() or poll_one() will return immediately until reset() is called.

    boost::system::error_code ec;
    size_t re = ios.poll_one(ec);
    std::cout << "poll after stop: handled " << re << ", stopped " << std::boolalpha << ios.stopped() << ", error " << ec << std::endl;
    return 0;
}

It still handles pending operations before stop, but task_io_service does not: http://coliru.stacked-crooked.com/a/de6781ab7e468add

Also I confused, why second poll does not stop service: http://coliru.stacked-crooked.com/a/c606cda60c443191

Small source fix makes using BoringSSL easier

I'm using BoringSSL with ASIO 1.11. BoringSSL is Google's downstream fork of OpenSSL that removes some of the cruft from OpenSSL while remaining source compatible. I've found three issues with ASIO, but I only really need one source fix (which is openssl-fork-agnostic):

diff --git a/asio/include/asio/ssl/detail/impl/openssl_init.ipp b/asio/include/asio/ssl/detail/impl/openssl_init.ipp
index 2c40d40..0229374 100644
--- a/asio/include/asio/ssl/detail/impl/openssl_init.ipp
+++ b/asio/include/asio/ssl/detail/impl/openssl_init.ipp
@@ -63,7 +63,11 @@ public:
     ::CRYPTO_set_id_callback(0);
     ::CRYPTO_set_locking_callback(0);
     ::ERR_free_strings();
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+    ::ERR_remove_thread_state(NULL);
+#else
     ::ERR_remove_state(0);
+#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
     ::EVP_cleanup();
     ::CRYPTO_cleanup_all_ex_data();
     ::CONF_modules_unload(1);

ERR_remove_state was deprecated in favor of ERR_remove_thread_state in OpenSSL 1.0.0 (although it remained for binary compatibility).

https://www.openssl.org/docs/crypto/ERR_remove_state.html

The other two issues are:

  1. CONF_modules_unload isn't declared or defined in BoringSSL. Config modules aren't supported.
  2. SSL_R_SHORT_READ isn't defined in BoringSSL. Unused error codes have been removed.

These last two issues can be handled in my own code with a header prefix:

#if defined(OPENSSL_IS_BORINGSSL)
extern "C" {
#if !defined(SSL_R_SHORT_READ)
# define SSL_R_SHORT_READ    SSL_R_UNEXPECTED_RECORD
#endif // !defined(SSL_R_SHORT_READ)
inline void CONF_modules_unload(int p) {}
}
#endif // defined(OPENSSL_IS_BORINGSSL)

Websocket support

Why HTTP support, but no websocket support? Websocketpp, not sure I like it.

Not all unit tests passing on FreeBSD 10.1

Note this is for Boost.ASIO from Boost 1.57. The kqueues reactor is quite broken on FreeBSD 10.1, completion handlers are being called immediately with no error when a null buffers async receive is being done, but I'll distill that into a test case and report it separately. Meanwhile, below is the Boost.ASIO unit test failure log for 1.57:

[ned@kate] ~/boost-release% ./b2 libs/asio/test
Performing configuration checks

    - has_icu builds           : yes (cached)
...patience...
...patience...
...found 4310 targets...
...updating 4 targets...
testing.capture-output bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.run
====== BEGIN OUTPUT ======
Running 2 test cases...
libs/asio/test/ip/multicast.cpp(164): error in "ip_multicast_runtime::test": check !have_v6 || !ec failed
libs/asio/test/ip/multicast.cpp(179): error in "ip_multicast_runtime::test": 22, Invalid argument
libs/asio/test/ip/multicast.cpp(195): error in "ip_multicast_runtime::test": 22, Invalid argument

*** 3 failures detected in test suite "Master Test Suite"

EXIT STATUS: 201
====== END OUTPUT ======

    LD_LIBRARY_PATH="/usr/home/ned/boost-release/bin.v2/libs/date_time/build/clang-linux-3.4.1/debug/threading-multi:/usr/home/ned/boost-release/bin.v2/libs/regex/build/clang-linux-3.4.1/debug/threading-multi:/usr/home/ned/boost-release/bin.v2/libs/system/build/clang-linux-3.4.1/debug/threading-multi:/usr/local/bin:/usr/local/lib:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH

    status=0
    if test $status -ne 0 ; then
        echo Skipping test execution due to testing.execute=off
        exit 0
    fi
     "bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast"   > "bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.output" 2>&1
    status=$?
    echo >> "bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.output"
    echo EXIT STATUS: $status >> "bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.output"
    if test $status -eq 0 ; then
        cp "bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.output" "bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.run"
    fi
    verbose=0
    if test $status -ne 0 ; then
        verbose=1
    fi
    if test $verbose -eq 1 ; then
        echo ====== BEGIN OUTPUT ======
        cat "bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.output"
        echo ====== END OUTPUT ======
    fi
    exit $status

...failed testing.capture-output bin.v2/libs/asio/test/ip_multicast.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast.run...
testing.capture-output bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.run
====== BEGIN OUTPUT ======
Running 2 test cases...
libs/asio/test/ip/multicast.cpp(164): error in "ip_multicast_runtime::test": check !have_v6 || !ec failed
libs/asio/test/ip/multicast.cpp(179): error in "ip_multicast_runtime::test": 22, Invalid argument
libs/asio/test/ip/multicast.cpp(195): error in "ip_multicast_runtime::test": 22, Invalid argument

*** 3 failures detected in test suite "Master Test Suite"

EXIT STATUS: 201
====== END OUTPUT ======

    LD_LIBRARY_PATH="/usr/home/ned/boost-release/bin.v2/libs/date_time/build/clang-linux-3.4.1/debug/threading-multi:/usr/home/ned/boost-release/bin.v2/libs/regex/build/clang-linux-3.4.1/debug/threading-multi:/usr/home/ned/boost-release/bin.v2/libs/system/build/clang-linux-3.4.1/debug/threading-multi:/usr/local/bin:/usr/local/lib:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH

    status=0
    if test $status -ne 0 ; then
        echo Skipping test execution due to testing.execute=off
        exit 0
    fi
     "bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select"   > "bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.output" 2>&1
    status=$?
    echo >> "bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.output"
    echo EXIT STATUS: $status >> "bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.output"
    if test $status -eq 0 ; then
        cp "bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.output" "bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.run"
    fi
    verbose=0
    if test $status -ne 0 ; then
        verbose=1
    fi
    if test $verbose -eq 1 ; then
        echo ====== BEGIN OUTPUT ======
        cat "bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.output"
        echo ====== END OUTPUT ======
    fi
    exit $status

...failed testing.capture-output bin.v2/libs/asio/test/ip_multicast_select.test/clang-linux-3.4.1/debug/threading-multi/ip_multicast_select.run...
...failed updating 2 targets...
...skipped 2 targets...

Use asio without boost, using mingw

/include/asio/detail/addressof.hpp:23:40: fatal error: boost/utility/addressof.hpp: No such file or directory.
ASIO_HAS_STD_ADDRESSOF should be defined

Incorrect handling of OpenSSL errors causes dropped connections

Asio does not handle errors reported by OpenSSL properly. This may (has for me) result in errors later on which are very hard to troubleshoot.

When an error occur in OpenSSL, errors-codes are pushed onto a queue. A single call to OpenSSL may result in multiple error-codes being pushed to the queue. For example, a low-level component in OpenSSL may push one error to the queue, while another higher-level component may push another.

After Asio has executed an SSL function, it only removes the first error from the queue. If more than one item have been pushed to the queue, the remaining items will be left behind in the queue. When Asio calls a SSL function later on, and checks the queue, it may pick up the error from a previous operation, and think that the current operation has faulted, even though it hasn't.

For example, you may call async_read and that will fail with an error related to loading of private keys, even though the call to load the private_key was made yesterday.

Easiest way to see this issue:

    context.set_password_callback(GetPasswordCallbackFunc);
    context.use_private_key_file(keyfile, boost::asio::ssl::context::pem);
    int err_after = ::ERR_peek_error();

Make sure that GetPasswordCallbackFunc reports an incorrect password, so that the private key file cannot be opened. When this happens, OpenSSL will push two errors to the error queue, but Asio will only remove the first item. The call to ::ERR_peek_error() will show that there are errors left behind in the queue. If you some point later in time tries to perform another SSL operation, such as async_read, that will fail because there's old items left on the error queue. Or rather, the actual read will succeed but Asio will report it as failed)

I tried clearing the queue in use_private_key_file but there are other SSL operations which pushes multiple errors to the queue. (I'm not sure which though)

Some of the functions in Asio calls....
::ERR_clear_error();
.. prior to do anything but far from all of them. According to what I've read, always calling this method prior to calling OpenSSL functions is the proper way to go.

context::use_private_key does not support encrypted PEM key

I'm using asio 1.10.4.

When I use the context::use_private_key_file API with an encrypted PEM private key, everything works fine; the key is decrypted using the context's password callback function.

When I use the context::use_private_key API under the same circumstances, OpenSSL asks me for the password instead.

Enter PEM pass phrase:

This surprised me, so I looked at the code in context.ipp. It loads the private key on line 630 without passing a password callback:

    case context_base::pem:
      evp_private_key.p = ::PEM_read_bio_PrivateKey(bio.p, 0, 0, 0);
      break;

I changed this line to:

    case context_base::pem:
      evp_private_key.p = ::PEM_read_bio_PrivateKey(bio.p, 0, handle_->default_passwd_callback, handle_->default_passwd_callback_userdata);
      break;

This fixed the problem. There is another call to PEM_read_bio_RSAPrivateKey where you may need to apply the same fix.

This issue is not fixed in the master branch.

Fails to compile with ASIO_NO_TYPEID, ASIO_ENABLE_HANDLER_TRACKING

I'm using the latest ASIO 1.11. When I define ASIO_NO_TYPEID and ASIO_ENABLE_HANDLER_TRACKING there are compilation errors.

The following changes appear to mitigate the errors.

diff --git a/asio/include/asio/detail/impl/strand_executor_service.hpp b/asio/include/asio/detail/impl/strand_exe
index 20cc24c..c518433 100644
--- a/asio/include/asio/detail/impl/strand_executor_service.hpp
+++ b/asio/include/asio/detail/impl/strand_executor_service.hpp
@@ -121,7 +121,7 @@ void strand_executor_service::dispatch(const implementation_type& impl,
   p.v = p.a.allocate(1);
   p.p = new (p.v) op(tmp, allocator);

-  ASIO_HANDLER_CREATION((p.p, "strand_executor", this, "dispatch"));
+  ASIO_HANDLER_CREATION((p.p, "strand_executor", &impl, "dispatch"));

   // Add the function to the strand and schedule the strand if required.
   bool first = enqueue(impl, p.p);
@@ -149,7 +149,7 @@ void strand_executor_service::post(const implementation_type& impl,
   p.v = p.a.allocate(1);
   p.p = new (p.v) op(tmp, allocator);

-  ASIO_HANDLER_CREATION((p.p, "strand_executor", this, "post"));
+  ASIO_HANDLER_CREATION((p.p, "strand_executor", &impl, "post"));

   // Add the function to the strand and schedule the strand if required.
   bool first = enqueue(impl, p.p);
@@ -177,7 +177,7 @@ void strand_executor_service::defer(const implementation_type& impl,
   p.v = p.a.allocate(1);
   p.p = new (p.v) op(tmp, allocator);

-  ASIO_HANDLER_CREATION((p.p, "strand_executor", this, "defer"));
+  ASIO_HANDLER_CREATION((p.p, "strand_executor", &impl, "defer"));

   // Add the function to the strand and schedule the strand if required.
   bool first = enqueue(impl, p.p);
diff --git a/asio/include/asio/executor.hpp b/asio/include/asio/executor.hpp
index a3b5730..2dec890 100644
--- a/asio/include/asio/executor.hpp
+++ b/asio/include/asio/executor.hpp
@@ -205,10 +205,12 @@ public:
    * @returns If @c *this has a target type of type @c T, <tt>typeid(T)</tt>;
    * otherwise, <tt>typeid(void)</tt>.
    */
+#if !defined(ASIO_NO_TYPEID)
   const std::type_info& target_type() const ASIO_NOEXCEPT
   {
     return impl_ ? impl_->target_type() : typeid(void);
   }
+#endif // !defined(ASIO_NO_TYPEID)

   /// Obtain a pointer to the target executor object.
   /**
diff --git a/asio/include/asio/impl/executor.hpp b/asio/include/asio/impl/executor.hpp
index d8bc403..40f7799 100644
--- a/asio/include/asio/impl/executor.hpp
+++ b/asio/include/asio/impl/executor.hpp
@@ -197,10 +197,12 @@ public:
     executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_);
   }

+#if !defined(ASIO_NO_TYPEID)
   const std::type_info& target_type() const ASIO_NOEXCEPT
   {
     return typeid(Executor);
   }
+#endif // !defined(ASIO_NO_TYPEID)

   void* target() ASIO_NOEXCEPT
   {
@@ -306,10 +308,12 @@ public:
     executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_);
   }

+#if !defined(ASIO_NO_TYPEID)
   const std::type_info& target_type() const ASIO_NOEXCEPT
   {
     return typeid(system_executor);
   }
+#endif // !defined(ASIO_NO_TYPEID)

   void* target() ASIO_NOEXCEPT
   {
@@ -365,6 +369,8 @@ void executor::defer(ASIO_MOVE_ARG(Function) f, const Allocator& a)
   get_impl()->defer(function(ASIO_MOVE_CAST(Function)(f), a));
 }

+#if !defined(ASIO_NO_TYPEID)
+
 template <typename Executor>
 Executor* executor::target() ASIO_NOEXCEPT
 {
@@ -379,6 +385,8 @@ const Executor* executor::target() const ASIO_NOEXCEPT
     ? static_cast<Executor*>(impl_->target()) : 0;
 }

+#endif // !defined(ASIO_NO_TYPEID)
+
 #endif // !defined(ASIO_NO_DEPRECATED)

 } // namespace asio

On an unrelated note, the #endif // !defined(ASIO_NO_DEPRECATED) near the end of the diff corresponds to a #if !defined(GENERATING_DOCUMENTATION) at the top of the file.

Fails to compile on VS14

c:\users\ned\documents\boost.afio\asio\asio\include\asio/impl/error_code.ipp(40): error C2694: 'const char *asio::detail::system_category::name(void) const': overriding virtual function has less restrictive exception specification than base class virtual member function 'const char *std::error_category::name(void) noexcept const'
c:\users\ned\documents\boost.afio\asio\asio\include\asio/impl/error_code.ipp(40): note: see declaration of 'asio::detail::system_category::name'
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(162): note: see declaration of 'std::error_category::name'
c:\users\ned\documents\boost.afio\asio\asio\include\asio/impl/error.ipp(96): error C2694: 'const char *asio::error::detail::misc_category::name(void) const': overriding virtual function has less restrictive exception specification than base class virtual member function 'const char *std::error_category::name(void) noexcept const'
c:\users\ned\documents\boost.afio\asio\asio\include\asio/impl/error.ipp(96): note: see declaration of 'asio::error::detail::misc_category::name'
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(162): note: see declaration of 'std::error_category::name'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.