diff options
Diffstat (limited to '3rdparty/asio/src/examples/cpp11')
166 files changed, 10765 insertions, 345 deletions
diff --git a/3rdparty/asio/src/examples/cpp11/Makefile.am b/3rdparty/asio/src/examples/cpp11/Makefile.am index bc2e1034021..a132a469ff5 100644 --- a/3rdparty/asio/src/examples/cpp11/Makefile.am +++ b/3rdparty/asio/src/examples/cpp11/Makefile.am @@ -14,6 +14,8 @@ noinst_PROGRAMS = \ buffers/reference_counted \ chat/chat_client \ chat/chat_server \ + deferred/deferred_1 \ + deferred/deferred_2 \ echo/async_tcp_echo_server \ echo/async_udp_echo_server \ echo/blocking_tcp_echo_client \ @@ -26,10 +28,20 @@ noinst_PROGRAMS = \ executors/fork_join \ executors/pipeline \ executors/priority_scheduler \ + files/blocking_file_copy \ + files/async_file_copy \ futures/daytime_client \ handler_tracking/async_tcp_echo_server \ + http/client/async_client \ + http/client/sync_client \ http/server/http_server \ + http/server2/http_server \ + http/server3/http_server \ + http/server4/http_server \ + icmp/ping \ invocation/prioritised_handlers \ + iostreams/daytime_client \ + iostreams/daytime_server \ iostreams/http_client \ multicast/receiver \ multicast/sender \ @@ -42,22 +54,51 @@ noinst_PROGRAMS = \ operations/composed_6 \ operations/composed_7 \ operations/composed_8 \ + parallel_group/ranged_wait_for_all \ + parallel_group/wait_for_all \ + parallel_group/wait_for_one \ + parallel_group/wait_for_one_error \ + parallel_group/wait_for_one_success \ + porthopper/client \ + porthopper/server \ + services/daytime_client \ socks4/sync_client \ timeouts/async_tcp_client \ timeouts/blocking_tcp_client \ timeouts/blocking_token_tcp_client \ timeouts/blocking_udp_client \ timeouts/server \ - timers/time_t_timer + timers/time_t_timer \ + tutorial/timer1/timer \ + tutorial/timer2/timer \ + tutorial/timer3/timer \ + tutorial/timer4/timer \ + tutorial/timer5/timer \ + tutorial/daytime1/client \ + tutorial/daytime2/server \ + tutorial/daytime3/server \ + tutorial/daytime4/client \ + tutorial/daytime5/server \ + tutorial/daytime6/server \ + tutorial/daytime7/server \ + type_erasure/type_erasure if !WINDOWS_TARGET noinst_PROGRAMS += \ + chat/posix_chat_client \ fork/daemon \ fork/process_per_connection \ local/connect_pair \ local/iostream_client \ local/stream_server \ - local/stream_client + local/stream_client \ + local/fd_passing_stream_server \ + local/fd_passing_stream_client +endif + +if WINDOWS_TARGET +noinst_PROGRAMS += \ + windows/transmit_file endif if HAVE_OPENSSL @@ -73,8 +114,51 @@ noinst_PROGRAMS += \ endif noinst_HEADERS = \ + chat/chat_message.hpp \ + handler_tracking/custom_tracking.hpp \ + http/server/connection.hpp \ + http/server/connection_manager.hpp \ + http/server/header.hpp \ + http/server/mime_types.hpp \ + http/server/reply.hpp \ + http/server/request.hpp \ + http/server/request_handler.hpp \ + http/server/request_parser.hpp \ + http/server/server.hpp \ + http/server2/connection.hpp \ + http/server2/io_context_pool.hpp \ + http/server2/header.hpp \ + http/server2/mime_types.hpp \ + http/server2/reply.hpp \ + http/server2/request.hpp \ + http/server2/request_handler.hpp \ + http/server2/request_parser.hpp \ + http/server2/server.hpp \ + http/server3/connection.hpp \ + http/server3/header.hpp \ + http/server3/mime_types.hpp \ + http/server3/reply.hpp \ + http/server3/request.hpp \ + http/server3/request_handler.hpp \ + http/server3/request_parser.hpp \ + http/server3/server.hpp \ + http/server4/file_handler.hpp \ + http/server4/header.hpp \ + http/server4/mime_types.hpp \ + http/server4/reply.hpp \ + http/server4/request.hpp \ + http/server4/request_parser.hpp \ + http/server4/server.hpp \ + icmp/icmp_header.hpp \ + icmp/ipv4_header.hpp \ + porthopper/protocol.hpp \ + services/basic_logger.hpp \ + services/logger.hpp \ + services/logger_service.hpp \ socks4/socks4.hpp \ - chat/chat_message.hpp + type_erasure/line_reader.hpp \ + type_erasure/stdin_line_reader.hpp \ + type_erasure/sleep.hpp AM_CXXFLAGS = -I$(srcdir)/../../../include @@ -82,6 +166,8 @@ allocation_server_SOURCES = allocation/server.cpp buffers_reference_counted_SOURCES = buffers/reference_counted.cpp chat_chat_client_SOURCES = chat/chat_client.cpp chat_chat_server_SOURCES = chat/chat_server.cpp +deferred_deferred_1_SOURCES = deferred/deferred_1.cpp +deferred_deferred_2_SOURCES = deferred/deferred_2.cpp echo_async_tcp_echo_server_SOURCES = echo/async_tcp_echo_server.cpp echo_async_udp_echo_server_SOURCES = echo/async_udp_echo_server.cpp echo_blocking_tcp_echo_client_SOURCES = echo/blocking_tcp_echo_client.cpp @@ -94,8 +180,12 @@ executors_bank_account_2_SOURCES = executors/bank_account_2.cpp executors_fork_join_SOURCES = executors/fork_join.cpp executors_pipeline_SOURCES = executors/pipeline.cpp executors_priority_scheduler_SOURCES = executors/priority_scheduler.cpp +files_blocking_file_copy_SOURCES = files/blocking_file_copy.cpp +files_async_file_copy_SOURCES = files/async_file_copy.cpp futures_daytime_client_SOURCES = futures/daytime_client.cpp handler_tracking_async_tcp_echo_server_SOURCES = handler_tracking/async_tcp_echo_server.cpp +http_client_async_client_SOURCES = http/client/async_client.cpp +http_client_sync_client_SOURCES = http/client/sync_client.cpp http_server_http_server_SOURCES = \ http/server/connection.cpp \ http/server/connection_manager.cpp \ @@ -105,7 +195,34 @@ http_server_http_server_SOURCES = \ http/server/request_handler.cpp \ http/server/request_parser.cpp \ http/server/server.cpp +http_server2_http_server_SOURCES = \ + http/server2/connection.cpp \ + http/server2/io_context_pool.cpp \ + http/server2/main.cpp \ + http/server2/mime_types.cpp \ + http/server2/reply.cpp \ + http/server2/request_handler.cpp \ + http/server2/request_parser.cpp \ + http/server2/server.cpp +http_server3_http_server_SOURCES = \ + http/server3/connection.cpp \ + http/server3/main.cpp \ + http/server3/mime_types.cpp \ + http/server3/reply.cpp \ + http/server3/request_handler.cpp \ + http/server3/request_parser.cpp \ + http/server3/server.cpp +http_server4_http_server_SOURCES = \ + http/server4/file_handler.cpp \ + http/server4/main.cpp \ + http/server4/mime_types.cpp \ + http/server4/reply.cpp \ + http/server4/request_parser.cpp \ + http/server4/server.cpp +icmp_ping_SOURCES = icmp/ping.cpp invocation_prioritised_handlers_SOURCES = invocation/prioritised_handlers.cpp +iostreams_daytime_client_SOURCES = iostreams/daytime_client.cpp +iostreams_daytime_server_SOURCES = iostreams/daytime_server.cpp iostreams_http_client_SOURCES = iostreams/http_client.cpp multicast_receiver_SOURCES = multicast/receiver.cpp multicast_sender_SOURCES = multicast/sender.cpp @@ -118,6 +235,16 @@ operations_composed_5_SOURCES = operations/composed_5.cpp operations_composed_6_SOURCES = operations/composed_6.cpp operations_composed_7_SOURCES = operations/composed_7.cpp operations_composed_8_SOURCES = operations/composed_8.cpp +parallel_group_ranged_wait_for_all_SOURCES = parallel_group/ranged_wait_for_all.cpp +parallel_group_wait_for_all_SOURCES = parallel_group/wait_for_all.cpp +parallel_group_wait_for_one_SOURCES = parallel_group/wait_for_one.cpp +parallel_group_wait_for_one_error_SOURCES = parallel_group/wait_for_one_error.cpp +parallel_group_wait_for_one_success_SOURCES = parallel_group/wait_for_one_success.cpp +porthopper_client_SOURCES = porthopper/client.cpp +porthopper_server_SOURCES = porthopper/server.cpp +services_daytime_client_SOURCES = \ + services/daytime_client.cpp \ + services/logger_service.cpp socks4_sync_client_SOURCES = socks4/sync_client.cpp timeouts_async_tcp_client_SOURCES = timeouts/async_tcp_client.cpp timeouts_blocking_tcp_client_SOURCES = timeouts/blocking_tcp_client.cpp @@ -125,14 +252,34 @@ timeouts_blocking_token_tcp_client_SOURCES = timeouts/blocking_token_tcp_client. timeouts_blocking_udp_client_SOURCES = timeouts/blocking_udp_client.cpp timeouts_server_SOURCES = timeouts/server.cpp timers_time_t_timer_SOURCES = timers/time_t_timer.cpp +tutorial_timer1_timer_SOURCES = tutorial/timer1/timer.cpp +tutorial_timer2_timer_SOURCES = tutorial/timer2/timer.cpp +tutorial_timer3_timer_SOURCES = tutorial/timer3/timer.cpp +tutorial_timer4_timer_SOURCES = tutorial/timer4/timer.cpp +tutorial_timer5_timer_SOURCES = tutorial/timer5/timer.cpp +tutorial_daytime1_client_SOURCES = tutorial/daytime1/client.cpp +tutorial_daytime2_server_SOURCES = tutorial/daytime2/server.cpp +tutorial_daytime3_server_SOURCES = tutorial/daytime3/server.cpp +tutorial_daytime4_client_SOURCES = tutorial/daytime4/client.cpp +tutorial_daytime5_server_SOURCES = tutorial/daytime5/server.cpp +tutorial_daytime6_server_SOURCES = tutorial/daytime6/server.cpp +tutorial_daytime7_server_SOURCES = tutorial/daytime7/server.cpp +type_erasure_type_erasure_SOURCES = type_erasure/main.cpp type_erasure/stdin_line_reader.cpp type_erasure/sleep.cpp if !WINDOWS_TARGET +chat_posix_chat_client_SOURCES = chat/posix_chat_client.cpp fork_daemon_SOURCES = fork/daemon.cpp fork_process_per_connection_SOURCES = fork/process_per_connection.cpp local_connect_pair_SOURCES = local/connect_pair.cpp local_iostream_client_SOURCES = local/iostream_client.cpp local_stream_server_SOURCES = local/stream_server.cpp local_stream_client_SOURCES = local/stream_client.cpp +local_fd_passing_stream_server_SOURCES = local/fd_passing_stream_server.cpp +local_fd_passing_stream_client_SOURCES = local/fd_passing_stream_client.cpp +endif + +if WINDOWS_TARGET +windows_transmit_file_SOURCES = windows/transmit_file.cpp endif if HAVE_OPENSSL @@ -148,16 +295,14 @@ spawn_parallel_grep_LDADD = $(LDADD) -lboost_coroutine -lboost_context -lboost_t endif EXTRA_DIST = \ - handler_tracking/custom_tracking.hpp \ - http/server/connection.hpp \ - http/server/connection_manager.hpp \ - http/server/header.hpp \ - http/server/mime_types.hpp \ - http/server/reply.hpp \ - http/server/request.hpp \ - http/server/request_handler.hpp \ - http/server/request_parser.hpp \ - http/server/server.hpp + serialization/client.cpp \ + serialization/server.cpp \ + serialization/connection.hpp \ + serialization/stock.hpp \ + ssl/README \ + ssl/ca.pem \ + ssl/server.pem \ + ssl/dh4096.pem MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in diff --git a/3rdparty/asio/src/examples/cpp11/Makefile.in b/3rdparty/asio/src/examples/cpp11/Makefile.in index beb10c2cce5..0f73bb5b85a 100644 --- a/3rdparty/asio/src/examples/cpp11/Makefile.in +++ b/3rdparty/asio/src/examples/cpp11/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -93,7 +93,9 @@ host_triplet = @host@ @HAVE_OPENSSL_TRUE@@SEPARATE_COMPILATION_TRUE@am__append_1 = ../../asio_ssl.cpp noinst_PROGRAMS = allocation/server$(EXEEXT) \ buffers/reference_counted$(EXEEXT) chat/chat_client$(EXEEXT) \ - chat/chat_server$(EXEEXT) echo/async_tcp_echo_server$(EXEEXT) \ + chat/chat_server$(EXEEXT) deferred/deferred_1$(EXEEXT) \ + deferred/deferred_2$(EXEEXT) \ + echo/async_tcp_echo_server$(EXEEXT) \ echo/async_udp_echo_server$(EXEEXT) \ echo/blocking_tcp_echo_client$(EXEEXT) \ echo/blocking_tcp_echo_server$(EXEEXT) \ @@ -103,35 +105,66 @@ noinst_PROGRAMS = allocation/server$(EXEEXT) \ executors/bank_account_2$(EXEEXT) executors/fork_join$(EXEEXT) \ executors/pipeline$(EXEEXT) \ executors/priority_scheduler$(EXEEXT) \ - futures/daytime_client$(EXEEXT) \ + files/blocking_file_copy$(EXEEXT) \ + files/async_file_copy$(EXEEXT) futures/daytime_client$(EXEEXT) \ handler_tracking/async_tcp_echo_server$(EXEEXT) \ + http/client/async_client$(EXEEXT) \ + http/client/sync_client$(EXEEXT) \ http/server/http_server$(EXEEXT) \ + http/server2/http_server$(EXEEXT) \ + http/server3/http_server$(EXEEXT) \ + http/server4/http_server$(EXEEXT) icmp/ping$(EXEEXT) \ invocation/prioritised_handlers$(EXEEXT) \ + iostreams/daytime_client$(EXEEXT) \ + iostreams/daytime_server$(EXEEXT) \ iostreams/http_client$(EXEEXT) multicast/receiver$(EXEEXT) \ multicast/sender$(EXEEXT) nonblocking/third_party_lib$(EXEEXT) \ operations/composed_1$(EXEEXT) operations/composed_2$(EXEEXT) \ operations/composed_3$(EXEEXT) operations/composed_4$(EXEEXT) \ operations/composed_5$(EXEEXT) operations/composed_6$(EXEEXT) \ operations/composed_7$(EXEEXT) operations/composed_8$(EXEEXT) \ - socks4/sync_client$(EXEEXT) timeouts/async_tcp_client$(EXEEXT) \ + parallel_group/ranged_wait_for_all$(EXEEXT) \ + parallel_group/wait_for_all$(EXEEXT) \ + parallel_group/wait_for_one$(EXEEXT) \ + parallel_group/wait_for_one_error$(EXEEXT) \ + parallel_group/wait_for_one_success$(EXEEXT) \ + porthopper/client$(EXEEXT) porthopper/server$(EXEEXT) \ + services/daytime_client$(EXEEXT) socks4/sync_client$(EXEEXT) \ + timeouts/async_tcp_client$(EXEEXT) \ timeouts/blocking_tcp_client$(EXEEXT) \ timeouts/blocking_token_tcp_client$(EXEEXT) \ timeouts/blocking_udp_client$(EXEEXT) timeouts/server$(EXEEXT) \ - timers/time_t_timer$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \ - $(am__EXEEXT_3) + timers/time_t_timer$(EXEEXT) tutorial/timer1/timer$(EXEEXT) \ + tutorial/timer2/timer$(EXEEXT) tutorial/timer3/timer$(EXEEXT) \ + tutorial/timer4/timer$(EXEEXT) tutorial/timer5/timer$(EXEEXT) \ + tutorial/daytime1/client$(EXEEXT) \ + tutorial/daytime2/server$(EXEEXT) \ + tutorial/daytime3/server$(EXEEXT) \ + tutorial/daytime4/client$(EXEEXT) \ + tutorial/daytime5/server$(EXEEXT) \ + tutorial/daytime6/server$(EXEEXT) \ + tutorial/daytime7/server$(EXEEXT) \ + type_erasure/type_erasure$(EXEEXT) $(am__EXEEXT_1) \ + $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) @WINDOWS_TARGET_FALSE@am__append_2 = \ +@WINDOWS_TARGET_FALSE@ chat/posix_chat_client \ @WINDOWS_TARGET_FALSE@ fork/daemon \ @WINDOWS_TARGET_FALSE@ fork/process_per_connection \ @WINDOWS_TARGET_FALSE@ local/connect_pair \ @WINDOWS_TARGET_FALSE@ local/iostream_client \ @WINDOWS_TARGET_FALSE@ local/stream_server \ -@WINDOWS_TARGET_FALSE@ local/stream_client +@WINDOWS_TARGET_FALSE@ local/stream_client \ +@WINDOWS_TARGET_FALSE@ local/fd_passing_stream_server \ +@WINDOWS_TARGET_FALSE@ local/fd_passing_stream_client -@HAVE_OPENSSL_TRUE@am__append_3 = \ +@WINDOWS_TARGET_TRUE@am__append_3 = \ +@WINDOWS_TARGET_TRUE@ windows/transmit_file + +@HAVE_OPENSSL_TRUE@am__append_4 = \ @HAVE_OPENSSL_TRUE@ ssl/client \ @HAVE_OPENSSL_TRUE@ ssl/server -@HAVE_BOOST_COROUTINE_TRUE@am__append_4 = \ +@HAVE_BOOST_COROUTINE_TRUE@am__append_5 = \ @HAVE_BOOST_COROUTINE_TRUE@ spawn/echo_server \ @HAVE_BOOST_COROUTINE_TRUE@ spawn/parallel_grep @@ -145,15 +178,19 @@ DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -@WINDOWS_TARGET_FALSE@am__EXEEXT_1 = fork/daemon$(EXEEXT) \ +@WINDOWS_TARGET_FALSE@am__EXEEXT_1 = chat/posix_chat_client$(EXEEXT) \ +@WINDOWS_TARGET_FALSE@ fork/daemon$(EXEEXT) \ @WINDOWS_TARGET_FALSE@ fork/process_per_connection$(EXEEXT) \ @WINDOWS_TARGET_FALSE@ local/connect_pair$(EXEEXT) \ @WINDOWS_TARGET_FALSE@ local/iostream_client$(EXEEXT) \ @WINDOWS_TARGET_FALSE@ local/stream_server$(EXEEXT) \ -@WINDOWS_TARGET_FALSE@ local/stream_client$(EXEEXT) -@HAVE_OPENSSL_TRUE@am__EXEEXT_2 = ssl/client$(EXEEXT) \ +@WINDOWS_TARGET_FALSE@ local/stream_client$(EXEEXT) \ +@WINDOWS_TARGET_FALSE@ local/fd_passing_stream_server$(EXEEXT) \ +@WINDOWS_TARGET_FALSE@ local/fd_passing_stream_client$(EXEEXT) +@WINDOWS_TARGET_TRUE@am__EXEEXT_2 = windows/transmit_file$(EXEEXT) +@HAVE_OPENSSL_TRUE@am__EXEEXT_3 = ssl/client$(EXEEXT) \ @HAVE_OPENSSL_TRUE@ ssl/server$(EXEEXT) -@HAVE_BOOST_COROUTINE_TRUE@am__EXEEXT_3 = spawn/echo_server$(EXEEXT) \ +@HAVE_BOOST_COROUTINE_TRUE@am__EXEEXT_4 = spawn/echo_server$(EXEEXT) \ @HAVE_BOOST_COROUTINE_TRUE@ spawn/parallel_grep$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) LIBRARIES = $(noinst_LIBRARIES) @@ -191,6 +228,23 @@ am_chat_chat_server_OBJECTS = chat/chat_server.$(OBJEXT) chat_chat_server_OBJECTS = $(am_chat_chat_server_OBJECTS) chat_chat_server_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@chat_chat_server_DEPENDENCIES = libasio.a +am__chat_posix_chat_client_SOURCES_DIST = chat/posix_chat_client.cpp +@WINDOWS_TARGET_FALSE@am_chat_posix_chat_client_OBJECTS = \ +@WINDOWS_TARGET_FALSE@ chat/posix_chat_client.$(OBJEXT) +chat_posix_chat_client_OBJECTS = $(am_chat_posix_chat_client_OBJECTS) +chat_posix_chat_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@chat_posix_chat_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_1_OBJECTS = deferred/deferred_1.$(OBJEXT) +deferred_deferred_1_OBJECTS = $(am_deferred_deferred_1_OBJECTS) +deferred_deferred_1_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_1_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_2_OBJECTS = deferred/deferred_2.$(OBJEXT) +deferred_deferred_2_OBJECTS = $(am_deferred_deferred_2_OBJECTS) +deferred_deferred_2_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_2_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a am_echo_async_tcp_echo_server_OBJECTS = \ echo/async_tcp_echo_server.$(OBJEXT) echo_async_tcp_echo_server_OBJECTS = \ @@ -268,6 +322,18 @@ executors_priority_scheduler_OBJECTS = \ executors_priority_scheduler_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@executors_priority_scheduler_DEPENDENCIES = \ @SEPARATE_COMPILATION_TRUE@ libasio.a +am_files_async_file_copy_OBJECTS = files/async_file_copy.$(OBJEXT) +files_async_file_copy_OBJECTS = $(am_files_async_file_copy_OBJECTS) +files_async_file_copy_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@files_async_file_copy_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_files_blocking_file_copy_OBJECTS = \ + files/blocking_file_copy.$(OBJEXT) +files_blocking_file_copy_OBJECTS = \ + $(am_files_blocking_file_copy_OBJECTS) +files_blocking_file_copy_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@files_blocking_file_copy_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a am__fork_daemon_SOURCES_DIST = fork/daemon.cpp @WINDOWS_TARGET_FALSE@am_fork_daemon_OBJECTS = fork/daemon.$(OBJEXT) fork_daemon_OBJECTS = $(am_fork_daemon_OBJECTS) @@ -294,6 +360,20 @@ handler_tracking_async_tcp_echo_server_OBJECTS = \ handler_tracking_async_tcp_echo_server_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@handler_tracking_async_tcp_echo_server_DEPENDENCIES = \ @SEPARATE_COMPILATION_TRUE@ libasio.a +am_http_client_async_client_OBJECTS = \ + http/client/async_client.$(OBJEXT) +http_client_async_client_OBJECTS = \ + $(am_http_client_async_client_OBJECTS) +http_client_async_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@http_client_async_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_http_client_sync_client_OBJECTS = \ + http/client/sync_client.$(OBJEXT) +http_client_sync_client_OBJECTS = \ + $(am_http_client_sync_client_OBJECTS) +http_client_sync_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@http_client_sync_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a am_http_server_http_server_OBJECTS = http/server/connection.$(OBJEXT) \ http/server/connection_manager.$(OBJEXT) \ http/server/main.$(OBJEXT) http/server/mime_types.$(OBJEXT) \ @@ -306,6 +386,45 @@ http_server_http_server_OBJECTS = \ http_server_http_server_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@http_server_http_server_DEPENDENCIES = \ @SEPARATE_COMPILATION_TRUE@ libasio.a +am_http_server2_http_server_OBJECTS = \ + http/server2/connection.$(OBJEXT) \ + http/server2/io_context_pool.$(OBJEXT) \ + http/server2/main.$(OBJEXT) http/server2/mime_types.$(OBJEXT) \ + http/server2/reply.$(OBJEXT) \ + http/server2/request_handler.$(OBJEXT) \ + http/server2/request_parser.$(OBJEXT) \ + http/server2/server.$(OBJEXT) +http_server2_http_server_OBJECTS = \ + $(am_http_server2_http_server_OBJECTS) +http_server2_http_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@http_server2_http_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_http_server3_http_server_OBJECTS = \ + http/server3/connection.$(OBJEXT) http/server3/main.$(OBJEXT) \ + http/server3/mime_types.$(OBJEXT) http/server3/reply.$(OBJEXT) \ + http/server3/request_handler.$(OBJEXT) \ + http/server3/request_parser.$(OBJEXT) \ + http/server3/server.$(OBJEXT) +http_server3_http_server_OBJECTS = \ + $(am_http_server3_http_server_OBJECTS) +http_server3_http_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@http_server3_http_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_http_server4_http_server_OBJECTS = \ + http/server4/file_handler.$(OBJEXT) \ + http/server4/main.$(OBJEXT) http/server4/mime_types.$(OBJEXT) \ + http/server4/reply.$(OBJEXT) \ + http/server4/request_parser.$(OBJEXT) \ + http/server4/server.$(OBJEXT) +http_server4_http_server_OBJECTS = \ + $(am_http_server4_http_server_OBJECTS) +http_server4_http_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@http_server4_http_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_icmp_ping_OBJECTS = icmp/ping.$(OBJEXT) +icmp_ping_OBJECTS = $(am_icmp_ping_OBJECTS) +icmp_ping_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@icmp_ping_DEPENDENCIES = libasio.a am_invocation_prioritised_handlers_OBJECTS = \ invocation/prioritised_handlers.$(OBJEXT) invocation_prioritised_handlers_OBJECTS = \ @@ -313,6 +432,20 @@ invocation_prioritised_handlers_OBJECTS = \ invocation_prioritised_handlers_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@invocation_prioritised_handlers_DEPENDENCIES = \ @SEPARATE_COMPILATION_TRUE@ libasio.a +am_iostreams_daytime_client_OBJECTS = \ + iostreams/daytime_client.$(OBJEXT) +iostreams_daytime_client_OBJECTS = \ + $(am_iostreams_daytime_client_OBJECTS) +iostreams_daytime_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@iostreams_daytime_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_iostreams_daytime_server_OBJECTS = \ + iostreams/daytime_server.$(OBJEXT) +iostreams_daytime_server_OBJECTS = \ + $(am_iostreams_daytime_server_OBJECTS) +iostreams_daytime_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@iostreams_daytime_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a am_iostreams_http_client_OBJECTS = iostreams/http_client.$(OBJEXT) iostreams_http_client_OBJECTS = $(am_iostreams_http_client_OBJECTS) iostreams_http_client_LDADD = $(LDADD) @@ -325,6 +458,22 @@ local_connect_pair_OBJECTS = $(am_local_connect_pair_OBJECTS) local_connect_pair_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@local_connect_pair_DEPENDENCIES = \ @SEPARATE_COMPILATION_TRUE@ libasio.a +am__local_fd_passing_stream_client_SOURCES_DIST = \ + local/fd_passing_stream_client.cpp +@WINDOWS_TARGET_FALSE@am_local_fd_passing_stream_client_OBJECTS = local/fd_passing_stream_client.$(OBJEXT) +local_fd_passing_stream_client_OBJECTS = \ + $(am_local_fd_passing_stream_client_OBJECTS) +local_fd_passing_stream_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@local_fd_passing_stream_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am__local_fd_passing_stream_server_SOURCES_DIST = \ + local/fd_passing_stream_server.cpp +@WINDOWS_TARGET_FALSE@am_local_fd_passing_stream_server_OBJECTS = local/fd_passing_stream_server.$(OBJEXT) +local_fd_passing_stream_server_OBJECTS = \ + $(am_local_fd_passing_stream_server_OBJECTS) +local_fd_passing_stream_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@local_fd_passing_stream_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a am__local_iostream_client_SOURCES_DIST = local/iostream_client.cpp @WINDOWS_TARGET_FALSE@am_local_iostream_client_OBJECTS = \ @WINDOWS_TARGET_FALSE@ local/iostream_client.$(OBJEXT) @@ -402,6 +551,57 @@ operations_composed_8_OBJECTS = $(am_operations_composed_8_OBJECTS) operations_composed_8_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@operations_composed_8_DEPENDENCIES = \ @SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_ranged_wait_for_all_OBJECTS = \ + parallel_group/ranged_wait_for_all.$(OBJEXT) +parallel_group_ranged_wait_for_all_OBJECTS = \ + $(am_parallel_group_ranged_wait_for_all_OBJECTS) +parallel_group_ranged_wait_for_all_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_ranged_wait_for_all_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_all_OBJECTS = \ + parallel_group/wait_for_all.$(OBJEXT) +parallel_group_wait_for_all_OBJECTS = \ + $(am_parallel_group_wait_for_all_OBJECTS) +parallel_group_wait_for_all_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_all_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_one_OBJECTS = \ + parallel_group/wait_for_one.$(OBJEXT) +parallel_group_wait_for_one_OBJECTS = \ + $(am_parallel_group_wait_for_one_OBJECTS) +parallel_group_wait_for_one_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_one_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_one_error_OBJECTS = \ + parallel_group/wait_for_one_error.$(OBJEXT) +parallel_group_wait_for_one_error_OBJECTS = \ + $(am_parallel_group_wait_for_one_error_OBJECTS) +parallel_group_wait_for_one_error_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_one_error_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_one_success_OBJECTS = \ + parallel_group/wait_for_one_success.$(OBJEXT) +parallel_group_wait_for_one_success_OBJECTS = \ + $(am_parallel_group_wait_for_one_success_OBJECTS) +parallel_group_wait_for_one_success_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_one_success_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_porthopper_client_OBJECTS = porthopper/client.$(OBJEXT) +porthopper_client_OBJECTS = $(am_porthopper_client_OBJECTS) +porthopper_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@porthopper_client_DEPENDENCIES = libasio.a +am_porthopper_server_OBJECTS = porthopper/server.$(OBJEXT) +porthopper_server_OBJECTS = $(am_porthopper_server_OBJECTS) +porthopper_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@porthopper_server_DEPENDENCIES = libasio.a +am_services_daytime_client_OBJECTS = \ + services/daytime_client.$(OBJEXT) \ + services/logger_service.$(OBJEXT) +services_daytime_client_OBJECTS = \ + $(am_services_daytime_client_OBJECTS) +services_daytime_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@services_daytime_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a am_socks4_sync_client_OBJECTS = socks4/sync_client.$(OBJEXT) socks4_sync_client_OBJECTS = $(am_socks4_sync_client_OBJECTS) socks4_sync_client_LDADD = $(LDADD) @@ -465,6 +665,95 @@ timers_time_t_timer_OBJECTS = $(am_timers_time_t_timer_OBJECTS) timers_time_t_timer_LDADD = $(LDADD) @SEPARATE_COMPILATION_TRUE@timers_time_t_timer_DEPENDENCIES = \ @SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_daytime1_client_OBJECTS = \ + tutorial/daytime1/client.$(OBJEXT) +tutorial_daytime1_client_OBJECTS = \ + $(am_tutorial_daytime1_client_OBJECTS) +tutorial_daytime1_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_daytime1_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_daytime2_server_OBJECTS = \ + tutorial/daytime2/server.$(OBJEXT) +tutorial_daytime2_server_OBJECTS = \ + $(am_tutorial_daytime2_server_OBJECTS) +tutorial_daytime2_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_daytime2_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_daytime3_server_OBJECTS = \ + tutorial/daytime3/server.$(OBJEXT) +tutorial_daytime3_server_OBJECTS = \ + $(am_tutorial_daytime3_server_OBJECTS) +tutorial_daytime3_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_daytime3_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_daytime4_client_OBJECTS = \ + tutorial/daytime4/client.$(OBJEXT) +tutorial_daytime4_client_OBJECTS = \ + $(am_tutorial_daytime4_client_OBJECTS) +tutorial_daytime4_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_daytime4_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_daytime5_server_OBJECTS = \ + tutorial/daytime5/server.$(OBJEXT) +tutorial_daytime5_server_OBJECTS = \ + $(am_tutorial_daytime5_server_OBJECTS) +tutorial_daytime5_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_daytime5_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_daytime6_server_OBJECTS = \ + tutorial/daytime6/server.$(OBJEXT) +tutorial_daytime6_server_OBJECTS = \ + $(am_tutorial_daytime6_server_OBJECTS) +tutorial_daytime6_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_daytime6_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_daytime7_server_OBJECTS = \ + tutorial/daytime7/server.$(OBJEXT) +tutorial_daytime7_server_OBJECTS = \ + $(am_tutorial_daytime7_server_OBJECTS) +tutorial_daytime7_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_daytime7_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_timer1_timer_OBJECTS = tutorial/timer1/timer.$(OBJEXT) +tutorial_timer1_timer_OBJECTS = $(am_tutorial_timer1_timer_OBJECTS) +tutorial_timer1_timer_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_timer1_timer_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_timer2_timer_OBJECTS = tutorial/timer2/timer.$(OBJEXT) +tutorial_timer2_timer_OBJECTS = $(am_tutorial_timer2_timer_OBJECTS) +tutorial_timer2_timer_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_timer2_timer_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_timer3_timer_OBJECTS = tutorial/timer3/timer.$(OBJEXT) +tutorial_timer3_timer_OBJECTS = $(am_tutorial_timer3_timer_OBJECTS) +tutorial_timer3_timer_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_timer3_timer_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_timer4_timer_OBJECTS = tutorial/timer4/timer.$(OBJEXT) +tutorial_timer4_timer_OBJECTS = $(am_tutorial_timer4_timer_OBJECTS) +tutorial_timer4_timer_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_timer4_timer_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_tutorial_timer5_timer_OBJECTS = tutorial/timer5/timer.$(OBJEXT) +tutorial_timer5_timer_OBJECTS = $(am_tutorial_timer5_timer_OBJECTS) +tutorial_timer5_timer_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@tutorial_timer5_timer_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_type_erasure_type_erasure_OBJECTS = type_erasure/main.$(OBJEXT) \ + type_erasure/stdin_line_reader.$(OBJEXT) \ + type_erasure/sleep.$(OBJEXT) +type_erasure_type_erasure_OBJECTS = \ + $(am_type_erasure_type_erasure_OBJECTS) +type_erasure_type_erasure_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@type_erasure_type_erasure_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am__windows_transmit_file_SOURCES_DIST = windows/transmit_file.cpp +@WINDOWS_TARGET_TRUE@am_windows_transmit_file_OBJECTS = \ +@WINDOWS_TARGET_TRUE@ windows/transmit_file.$(OBJEXT) +windows_transmit_file_OBJECTS = $(am_windows_transmit_file_OBJECTS) +windows_transmit_file_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@windows_transmit_file_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -484,6 +773,9 @@ am__depfiles_remade = ../../$(DEPDIR)/asio.Po \ ../../$(DEPDIR)/asio_ssl.Po allocation/$(DEPDIR)/server.Po \ buffers/$(DEPDIR)/reference_counted.Po \ chat/$(DEPDIR)/chat_client.Po chat/$(DEPDIR)/chat_server.Po \ + chat/$(DEPDIR)/posix_chat_client.Po \ + deferred/$(DEPDIR)/deferred_1.Po \ + deferred/$(DEPDIR)/deferred_2.Po \ echo/$(DEPDIR)/async_tcp_echo_server.Po \ echo/$(DEPDIR)/async_udp_echo_server.Po \ echo/$(DEPDIR)/blocking_tcp_echo_client.Po \ @@ -496,10 +788,13 @@ am__depfiles_remade = ../../$(DEPDIR)/asio.Po \ executors/$(DEPDIR)/fork_join.Po \ executors/$(DEPDIR)/pipeline.Po \ executors/$(DEPDIR)/priority_scheduler.Po \ - fork/$(DEPDIR)/daemon.Po \ + files/$(DEPDIR)/async_file_copy.Po \ + files/$(DEPDIR)/blocking_file_copy.Po fork/$(DEPDIR)/daemon.Po \ fork/$(DEPDIR)/process_per_connection.Po \ futures/$(DEPDIR)/daytime_client.Po \ handler_tracking/$(DEPDIR)/async_tcp_echo_server.Po \ + http/client/$(DEPDIR)/async_client.Po \ + http/client/$(DEPDIR)/sync_client.Po \ http/server/$(DEPDIR)/connection.Po \ http/server/$(DEPDIR)/connection_manager.Po \ http/server/$(DEPDIR)/main.Po \ @@ -508,9 +803,34 @@ am__depfiles_remade = ../../$(DEPDIR)/asio.Po \ http/server/$(DEPDIR)/request_handler.Po \ http/server/$(DEPDIR)/request_parser.Po \ http/server/$(DEPDIR)/server.Po \ + http/server2/$(DEPDIR)/connection.Po \ + http/server2/$(DEPDIR)/io_context_pool.Po \ + http/server2/$(DEPDIR)/main.Po \ + http/server2/$(DEPDIR)/mime_types.Po \ + http/server2/$(DEPDIR)/reply.Po \ + http/server2/$(DEPDIR)/request_handler.Po \ + http/server2/$(DEPDIR)/request_parser.Po \ + http/server2/$(DEPDIR)/server.Po \ + http/server3/$(DEPDIR)/connection.Po \ + http/server3/$(DEPDIR)/main.Po \ + http/server3/$(DEPDIR)/mime_types.Po \ + http/server3/$(DEPDIR)/reply.Po \ + http/server3/$(DEPDIR)/request_handler.Po \ + http/server3/$(DEPDIR)/request_parser.Po \ + http/server3/$(DEPDIR)/server.Po \ + http/server4/$(DEPDIR)/file_handler.Po \ + http/server4/$(DEPDIR)/main.Po \ + http/server4/$(DEPDIR)/mime_types.Po \ + http/server4/$(DEPDIR)/reply.Po \ + http/server4/$(DEPDIR)/request_parser.Po \ + http/server4/$(DEPDIR)/server.Po icmp/$(DEPDIR)/ping.Po \ invocation/$(DEPDIR)/prioritised_handlers.Po \ + iostreams/$(DEPDIR)/daytime_client.Po \ + iostreams/$(DEPDIR)/daytime_server.Po \ iostreams/$(DEPDIR)/http_client.Po \ local/$(DEPDIR)/connect_pair.Po \ + local/$(DEPDIR)/fd_passing_stream_client.Po \ + local/$(DEPDIR)/fd_passing_stream_server.Po \ local/$(DEPDIR)/iostream_client.Po \ local/$(DEPDIR)/stream_client.Po \ local/$(DEPDIR)/stream_server.Po \ @@ -524,13 +844,36 @@ am__depfiles_remade = ../../$(DEPDIR)/asio.Po \ operations/$(DEPDIR)/composed_6.Po \ operations/$(DEPDIR)/composed_7.Po \ operations/$(DEPDIR)/composed_8.Po \ + parallel_group/$(DEPDIR)/ranged_wait_for_all.Po \ + parallel_group/$(DEPDIR)/wait_for_all.Po \ + parallel_group/$(DEPDIR)/wait_for_one.Po \ + parallel_group/$(DEPDIR)/wait_for_one_error.Po \ + parallel_group/$(DEPDIR)/wait_for_one_success.Po \ + porthopper/$(DEPDIR)/client.Po porthopper/$(DEPDIR)/server.Po \ + services/$(DEPDIR)/daytime_client.Po \ + services/$(DEPDIR)/logger_service.Po \ socks4/$(DEPDIR)/sync_client.Po spawn/$(DEPDIR)/echo_server.Po \ spawn/$(DEPDIR)/parallel_grep.Po ssl/$(DEPDIR)/client.Po \ ssl/$(DEPDIR)/server.Po timeouts/$(DEPDIR)/async_tcp_client.Po \ timeouts/$(DEPDIR)/blocking_tcp_client.Po \ timeouts/$(DEPDIR)/blocking_token_tcp_client.Po \ timeouts/$(DEPDIR)/blocking_udp_client.Po \ - timeouts/$(DEPDIR)/server.Po timers/$(DEPDIR)/time_t_timer.Po + timeouts/$(DEPDIR)/server.Po timers/$(DEPDIR)/time_t_timer.Po \ + tutorial/daytime1/$(DEPDIR)/client.Po \ + tutorial/daytime2/$(DEPDIR)/server.Po \ + tutorial/daytime3/$(DEPDIR)/server.Po \ + tutorial/daytime4/$(DEPDIR)/client.Po \ + tutorial/daytime5/$(DEPDIR)/server.Po \ + tutorial/daytime6/$(DEPDIR)/server.Po \ + tutorial/daytime7/$(DEPDIR)/server.Po \ + tutorial/timer1/$(DEPDIR)/timer.Po \ + tutorial/timer2/$(DEPDIR)/timer.Po \ + tutorial/timer3/$(DEPDIR)/timer.Po \ + tutorial/timer4/$(DEPDIR)/timer.Po \ + tutorial/timer5/$(DEPDIR)/timer.Po \ + type_erasure/$(DEPDIR)/main.Po type_erasure/$(DEPDIR)/sleep.Po \ + type_erasure/$(DEPDIR)/stdin_line_reader.Po \ + windows/$(DEPDIR)/transmit_file.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -548,6 +891,8 @@ am__v_CXXLD_1 = SOURCES = $(libasio_a_SOURCES) $(allocation_server_SOURCES) \ $(buffers_reference_counted_SOURCES) \ $(chat_chat_client_SOURCES) $(chat_chat_server_SOURCES) \ + $(chat_posix_chat_client_SOURCES) \ + $(deferred_deferred_1_SOURCES) $(deferred_deferred_2_SOURCES) \ $(echo_async_tcp_echo_server_SOURCES) \ $(echo_async_udp_echo_server_SOURCES) \ $(echo_blocking_tcp_echo_client_SOURCES) \ @@ -557,13 +902,24 @@ SOURCES = $(libasio_a_SOURCES) $(allocation_server_SOURCES) \ $(executors_actor_SOURCES) $(executors_bank_account_1_SOURCES) \ $(executors_bank_account_2_SOURCES) \ $(executors_fork_join_SOURCES) $(executors_pipeline_SOURCES) \ - $(executors_priority_scheduler_SOURCES) $(fork_daemon_SOURCES) \ + $(executors_priority_scheduler_SOURCES) \ + $(files_async_file_copy_SOURCES) \ + $(files_blocking_file_copy_SOURCES) $(fork_daemon_SOURCES) \ $(fork_process_per_connection_SOURCES) \ $(futures_daytime_client_SOURCES) \ $(handler_tracking_async_tcp_echo_server_SOURCES) \ + $(http_client_async_client_SOURCES) \ + $(http_client_sync_client_SOURCES) \ $(http_server_http_server_SOURCES) \ + $(http_server2_http_server_SOURCES) \ + $(http_server3_http_server_SOURCES) \ + $(http_server4_http_server_SOURCES) $(icmp_ping_SOURCES) \ $(invocation_prioritised_handlers_SOURCES) \ + $(iostreams_daytime_client_SOURCES) \ + $(iostreams_daytime_server_SOURCES) \ $(iostreams_http_client_SOURCES) $(local_connect_pair_SOURCES) \ + $(local_fd_passing_stream_client_SOURCES) \ + $(local_fd_passing_stream_server_SOURCES) \ $(local_iostream_client_SOURCES) \ $(local_stream_client_SOURCES) $(local_stream_server_SOURCES) \ $(multicast_receiver_SOURCES) $(multicast_sender_SOURCES) \ @@ -575,18 +931,41 @@ SOURCES = $(libasio_a_SOURCES) $(allocation_server_SOURCES) \ $(operations_composed_5_SOURCES) \ $(operations_composed_6_SOURCES) \ $(operations_composed_7_SOURCES) \ - $(operations_composed_8_SOURCES) $(socks4_sync_client_SOURCES) \ - $(spawn_echo_server_SOURCES) $(spawn_parallel_grep_SOURCES) \ - $(ssl_client_SOURCES) $(ssl_server_SOURCES) \ - $(timeouts_async_tcp_client_SOURCES) \ + $(operations_composed_8_SOURCES) \ + $(parallel_group_ranged_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_one_SOURCES) \ + $(parallel_group_wait_for_one_error_SOURCES) \ + $(parallel_group_wait_for_one_success_SOURCES) \ + $(porthopper_client_SOURCES) $(porthopper_server_SOURCES) \ + $(services_daytime_client_SOURCES) \ + $(socks4_sync_client_SOURCES) $(spawn_echo_server_SOURCES) \ + $(spawn_parallel_grep_SOURCES) $(ssl_client_SOURCES) \ + $(ssl_server_SOURCES) $(timeouts_async_tcp_client_SOURCES) \ $(timeouts_blocking_tcp_client_SOURCES) \ $(timeouts_blocking_token_tcp_client_SOURCES) \ $(timeouts_blocking_udp_client_SOURCES) \ - $(timeouts_server_SOURCES) $(timers_time_t_timer_SOURCES) + $(timeouts_server_SOURCES) $(timers_time_t_timer_SOURCES) \ + $(tutorial_daytime1_client_SOURCES) \ + $(tutorial_daytime2_server_SOURCES) \ + $(tutorial_daytime3_server_SOURCES) \ + $(tutorial_daytime4_client_SOURCES) \ + $(tutorial_daytime5_server_SOURCES) \ + $(tutorial_daytime6_server_SOURCES) \ + $(tutorial_daytime7_server_SOURCES) \ + $(tutorial_timer1_timer_SOURCES) \ + $(tutorial_timer2_timer_SOURCES) \ + $(tutorial_timer3_timer_SOURCES) \ + $(tutorial_timer4_timer_SOURCES) \ + $(tutorial_timer5_timer_SOURCES) \ + $(type_erasure_type_erasure_SOURCES) \ + $(windows_transmit_file_SOURCES) DIST_SOURCES = $(am__libasio_a_SOURCES_DIST) \ $(allocation_server_SOURCES) \ $(buffers_reference_counted_SOURCES) \ $(chat_chat_client_SOURCES) $(chat_chat_server_SOURCES) \ + $(am__chat_posix_chat_client_SOURCES_DIST) \ + $(deferred_deferred_1_SOURCES) $(deferred_deferred_2_SOURCES) \ $(echo_async_tcp_echo_server_SOURCES) \ $(echo_async_udp_echo_server_SOURCES) \ $(echo_blocking_tcp_echo_client_SOURCES) \ @@ -597,14 +976,25 @@ DIST_SOURCES = $(am__libasio_a_SOURCES_DIST) \ $(executors_bank_account_2_SOURCES) \ $(executors_fork_join_SOURCES) $(executors_pipeline_SOURCES) \ $(executors_priority_scheduler_SOURCES) \ + $(files_async_file_copy_SOURCES) \ + $(files_blocking_file_copy_SOURCES) \ $(am__fork_daemon_SOURCES_DIST) \ $(am__fork_process_per_connection_SOURCES_DIST) \ $(futures_daytime_client_SOURCES) \ $(handler_tracking_async_tcp_echo_server_SOURCES) \ + $(http_client_async_client_SOURCES) \ + $(http_client_sync_client_SOURCES) \ $(http_server_http_server_SOURCES) \ + $(http_server2_http_server_SOURCES) \ + $(http_server3_http_server_SOURCES) \ + $(http_server4_http_server_SOURCES) $(icmp_ping_SOURCES) \ $(invocation_prioritised_handlers_SOURCES) \ + $(iostreams_daytime_client_SOURCES) \ + $(iostreams_daytime_server_SOURCES) \ $(iostreams_http_client_SOURCES) \ $(am__local_connect_pair_SOURCES_DIST) \ + $(am__local_fd_passing_stream_client_SOURCES_DIST) \ + $(am__local_fd_passing_stream_server_SOURCES_DIST) \ $(am__local_iostream_client_SOURCES_DIST) \ $(am__local_stream_client_SOURCES_DIST) \ $(am__local_stream_server_SOURCES_DIST) \ @@ -617,7 +1007,15 @@ DIST_SOURCES = $(am__libasio_a_SOURCES_DIST) \ $(operations_composed_5_SOURCES) \ $(operations_composed_6_SOURCES) \ $(operations_composed_7_SOURCES) \ - $(operations_composed_8_SOURCES) $(socks4_sync_client_SOURCES) \ + $(operations_composed_8_SOURCES) \ + $(parallel_group_ranged_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_one_SOURCES) \ + $(parallel_group_wait_for_one_error_SOURCES) \ + $(parallel_group_wait_for_one_success_SOURCES) \ + $(porthopper_client_SOURCES) $(porthopper_server_SOURCES) \ + $(services_daytime_client_SOURCES) \ + $(socks4_sync_client_SOURCES) \ $(am__spawn_echo_server_SOURCES_DIST) \ $(am__spawn_parallel_grep_SOURCES_DIST) \ $(am__ssl_client_SOURCES_DIST) $(am__ssl_server_SOURCES_DIST) \ @@ -625,7 +1023,21 @@ DIST_SOURCES = $(am__libasio_a_SOURCES_DIST) \ $(timeouts_blocking_tcp_client_SOURCES) \ $(timeouts_blocking_token_tcp_client_SOURCES) \ $(timeouts_blocking_udp_client_SOURCES) \ - $(timeouts_server_SOURCES) $(timers_time_t_timer_SOURCES) + $(timeouts_server_SOURCES) $(timers_time_t_timer_SOURCES) \ + $(tutorial_daytime1_client_SOURCES) \ + $(tutorial_daytime2_server_SOURCES) \ + $(tutorial_daytime3_server_SOURCES) \ + $(tutorial_daytime4_client_SOURCES) \ + $(tutorial_daytime5_server_SOURCES) \ + $(tutorial_daytime6_server_SOURCES) \ + $(tutorial_daytime7_server_SOURCES) \ + $(tutorial_timer1_timer_SOURCES) \ + $(tutorial_timer2_timer_SOURCES) \ + $(tutorial_timer3_timer_SOURCES) \ + $(tutorial_timer4_timer_SOURCES) \ + $(tutorial_timer5_timer_SOURCES) \ + $(type_erasure_type_erasure_SOURCES) \ + $(am__windows_transmit_file_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -649,8 +1061,6 @@ am__define_uniq_tagged_files = \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ @@ -664,8 +1074,9 @@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ CXX = @CXX@ -CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -674,9 +1085,8 @@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ -EGREP = @EGREP@ +ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -743,9 +1153,11 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -760,14 +1172,59 @@ AUTOMAKE_OPTIONS = subdir-objects @SEPARATE_COMPILATION_TRUE@ $(am__append_1) @SEPARATE_COMPILATION_TRUE@LDADD = libasio.a noinst_HEADERS = \ + chat/chat_message.hpp \ + handler_tracking/custom_tracking.hpp \ + http/server/connection.hpp \ + http/server/connection_manager.hpp \ + http/server/header.hpp \ + http/server/mime_types.hpp \ + http/server/reply.hpp \ + http/server/request.hpp \ + http/server/request_handler.hpp \ + http/server/request_parser.hpp \ + http/server/server.hpp \ + http/server2/connection.hpp \ + http/server2/io_context_pool.hpp \ + http/server2/header.hpp \ + http/server2/mime_types.hpp \ + http/server2/reply.hpp \ + http/server2/request.hpp \ + http/server2/request_handler.hpp \ + http/server2/request_parser.hpp \ + http/server2/server.hpp \ + http/server3/connection.hpp \ + http/server3/header.hpp \ + http/server3/mime_types.hpp \ + http/server3/reply.hpp \ + http/server3/request.hpp \ + http/server3/request_handler.hpp \ + http/server3/request_parser.hpp \ + http/server3/server.hpp \ + http/server4/file_handler.hpp \ + http/server4/header.hpp \ + http/server4/mime_types.hpp \ + http/server4/reply.hpp \ + http/server4/request.hpp \ + http/server4/request_parser.hpp \ + http/server4/server.hpp \ + icmp/icmp_header.hpp \ + icmp/ipv4_header.hpp \ + porthopper/protocol.hpp \ + services/basic_logger.hpp \ + services/logger.hpp \ + services/logger_service.hpp \ socks4/socks4.hpp \ - chat/chat_message.hpp + type_erasure/line_reader.hpp \ + type_erasure/stdin_line_reader.hpp \ + type_erasure/sleep.hpp AM_CXXFLAGS = -I$(srcdir)/../../../include allocation_server_SOURCES = allocation/server.cpp buffers_reference_counted_SOURCES = buffers/reference_counted.cpp chat_chat_client_SOURCES = chat/chat_client.cpp chat_chat_server_SOURCES = chat/chat_server.cpp +deferred_deferred_1_SOURCES = deferred/deferred_1.cpp +deferred_deferred_2_SOURCES = deferred/deferred_2.cpp echo_async_tcp_echo_server_SOURCES = echo/async_tcp_echo_server.cpp echo_async_udp_echo_server_SOURCES = echo/async_udp_echo_server.cpp echo_blocking_tcp_echo_client_SOURCES = echo/blocking_tcp_echo_client.cpp @@ -780,8 +1237,12 @@ executors_bank_account_2_SOURCES = executors/bank_account_2.cpp executors_fork_join_SOURCES = executors/fork_join.cpp executors_pipeline_SOURCES = executors/pipeline.cpp executors_priority_scheduler_SOURCES = executors/priority_scheduler.cpp +files_blocking_file_copy_SOURCES = files/blocking_file_copy.cpp +files_async_file_copy_SOURCES = files/async_file_copy.cpp futures_daytime_client_SOURCES = futures/daytime_client.cpp handler_tracking_async_tcp_echo_server_SOURCES = handler_tracking/async_tcp_echo_server.cpp +http_client_async_client_SOURCES = http/client/async_client.cpp +http_client_sync_client_SOURCES = http/client/sync_client.cpp http_server_http_server_SOURCES = \ http/server/connection.cpp \ http/server/connection_manager.cpp \ @@ -792,7 +1253,37 @@ http_server_http_server_SOURCES = \ http/server/request_parser.cpp \ http/server/server.cpp +http_server2_http_server_SOURCES = \ + http/server2/connection.cpp \ + http/server2/io_context_pool.cpp \ + http/server2/main.cpp \ + http/server2/mime_types.cpp \ + http/server2/reply.cpp \ + http/server2/request_handler.cpp \ + http/server2/request_parser.cpp \ + http/server2/server.cpp + +http_server3_http_server_SOURCES = \ + http/server3/connection.cpp \ + http/server3/main.cpp \ + http/server3/mime_types.cpp \ + http/server3/reply.cpp \ + http/server3/request_handler.cpp \ + http/server3/request_parser.cpp \ + http/server3/server.cpp + +http_server4_http_server_SOURCES = \ + http/server4/file_handler.cpp \ + http/server4/main.cpp \ + http/server4/mime_types.cpp \ + http/server4/reply.cpp \ + http/server4/request_parser.cpp \ + http/server4/server.cpp + +icmp_ping_SOURCES = icmp/ping.cpp invocation_prioritised_handlers_SOURCES = invocation/prioritised_handlers.cpp +iostreams_daytime_client_SOURCES = iostreams/daytime_client.cpp +iostreams_daytime_server_SOURCES = iostreams/daytime_server.cpp iostreams_http_client_SOURCES = iostreams/http_client.cpp multicast_receiver_SOURCES = multicast/receiver.cpp multicast_sender_SOURCES = multicast/sender.cpp @@ -805,6 +1296,17 @@ operations_composed_5_SOURCES = operations/composed_5.cpp operations_composed_6_SOURCES = operations/composed_6.cpp operations_composed_7_SOURCES = operations/composed_7.cpp operations_composed_8_SOURCES = operations/composed_8.cpp +parallel_group_ranged_wait_for_all_SOURCES = parallel_group/ranged_wait_for_all.cpp +parallel_group_wait_for_all_SOURCES = parallel_group/wait_for_all.cpp +parallel_group_wait_for_one_SOURCES = parallel_group/wait_for_one.cpp +parallel_group_wait_for_one_error_SOURCES = parallel_group/wait_for_one_error.cpp +parallel_group_wait_for_one_success_SOURCES = parallel_group/wait_for_one_success.cpp +porthopper_client_SOURCES = porthopper/client.cpp +porthopper_server_SOURCES = porthopper/server.cpp +services_daytime_client_SOURCES = \ + services/daytime_client.cpp \ + services/logger_service.cpp + socks4_sync_client_SOURCES = socks4/sync_client.cpp timeouts_async_tcp_client_SOURCES = timeouts/async_tcp_client.cpp timeouts_blocking_tcp_client_SOURCES = timeouts/blocking_tcp_client.cpp @@ -812,12 +1314,29 @@ timeouts_blocking_token_tcp_client_SOURCES = timeouts/blocking_token_tcp_client. timeouts_blocking_udp_client_SOURCES = timeouts/blocking_udp_client.cpp timeouts_server_SOURCES = timeouts/server.cpp timers_time_t_timer_SOURCES = timers/time_t_timer.cpp +tutorial_timer1_timer_SOURCES = tutorial/timer1/timer.cpp +tutorial_timer2_timer_SOURCES = tutorial/timer2/timer.cpp +tutorial_timer3_timer_SOURCES = tutorial/timer3/timer.cpp +tutorial_timer4_timer_SOURCES = tutorial/timer4/timer.cpp +tutorial_timer5_timer_SOURCES = tutorial/timer5/timer.cpp +tutorial_daytime1_client_SOURCES = tutorial/daytime1/client.cpp +tutorial_daytime2_server_SOURCES = tutorial/daytime2/server.cpp +tutorial_daytime3_server_SOURCES = tutorial/daytime3/server.cpp +tutorial_daytime4_client_SOURCES = tutorial/daytime4/client.cpp +tutorial_daytime5_server_SOURCES = tutorial/daytime5/server.cpp +tutorial_daytime6_server_SOURCES = tutorial/daytime6/server.cpp +tutorial_daytime7_server_SOURCES = tutorial/daytime7/server.cpp +type_erasure_type_erasure_SOURCES = type_erasure/main.cpp type_erasure/stdin_line_reader.cpp type_erasure/sleep.cpp +@WINDOWS_TARGET_FALSE@chat_posix_chat_client_SOURCES = chat/posix_chat_client.cpp @WINDOWS_TARGET_FALSE@fork_daemon_SOURCES = fork/daemon.cpp @WINDOWS_TARGET_FALSE@fork_process_per_connection_SOURCES = fork/process_per_connection.cpp @WINDOWS_TARGET_FALSE@local_connect_pair_SOURCES = local/connect_pair.cpp @WINDOWS_TARGET_FALSE@local_iostream_client_SOURCES = local/iostream_client.cpp @WINDOWS_TARGET_FALSE@local_stream_server_SOURCES = local/stream_server.cpp @WINDOWS_TARGET_FALSE@local_stream_client_SOURCES = local/stream_client.cpp +@WINDOWS_TARGET_FALSE@local_fd_passing_stream_server_SOURCES = local/fd_passing_stream_server.cpp +@WINDOWS_TARGET_FALSE@local_fd_passing_stream_client_SOURCES = local/fd_passing_stream_client.cpp +@WINDOWS_TARGET_TRUE@windows_transmit_file_SOURCES = windows/transmit_file.cpp @HAVE_OPENSSL_TRUE@ssl_client_SOURCES = ssl/client.cpp @HAVE_OPENSSL_TRUE@ssl_server_SOURCES = ssl/server.cpp @HAVE_BOOST_COROUTINE_TRUE@spawn_echo_server_SOURCES = spawn/echo_server.cpp @@ -825,16 +1344,14 @@ timers_time_t_timer_SOURCES = timers/time_t_timer.cpp @HAVE_BOOST_COROUTINE_TRUE@spawn_parallel_grep_SOURCES = spawn/parallel_grep.cpp @HAVE_BOOST_COROUTINE_TRUE@spawn_parallel_grep_LDADD = $(LDADD) -lboost_coroutine -lboost_context -lboost_thread -lboost_chrono -lboost_system EXTRA_DIST = \ - handler_tracking/custom_tracking.hpp \ - http/server/connection.hpp \ - http/server/connection_manager.hpp \ - http/server/header.hpp \ - http/server/mime_types.hpp \ - http/server/reply.hpp \ - http/server/request.hpp \ - http/server/request_handler.hpp \ - http/server/request_parser.hpp \ - http/server/server.hpp + serialization/client.cpp \ + serialization/server.cpp \ + serialization/connection.hpp \ + serialization/stock.hpp \ + ssl/README \ + ssl/ca.pem \ + ssl/server.pem \ + ssl/dh4096.pem MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in @@ -935,6 +1452,30 @@ chat/chat_server.$(OBJEXT): chat/$(am__dirstamp) \ chat/chat_server$(EXEEXT): $(chat_chat_server_OBJECTS) $(chat_chat_server_DEPENDENCIES) $(EXTRA_chat_chat_server_DEPENDENCIES) chat/$(am__dirstamp) @rm -f chat/chat_server$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(chat_chat_server_OBJECTS) $(chat_chat_server_LDADD) $(LIBS) +chat/posix_chat_client.$(OBJEXT): chat/$(am__dirstamp) \ + chat/$(DEPDIR)/$(am__dirstamp) + +chat/posix_chat_client$(EXEEXT): $(chat_posix_chat_client_OBJECTS) $(chat_posix_chat_client_DEPENDENCIES) $(EXTRA_chat_posix_chat_client_DEPENDENCIES) chat/$(am__dirstamp) + @rm -f chat/posix_chat_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(chat_posix_chat_client_OBJECTS) $(chat_posix_chat_client_LDADD) $(LIBS) +deferred/$(am__dirstamp): + @$(MKDIR_P) deferred + @: > deferred/$(am__dirstamp) +deferred/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) deferred/$(DEPDIR) + @: > deferred/$(DEPDIR)/$(am__dirstamp) +deferred/deferred_1.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_1$(EXEEXT): $(deferred_deferred_1_OBJECTS) $(deferred_deferred_1_DEPENDENCIES) $(EXTRA_deferred_deferred_1_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_1$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_1_OBJECTS) $(deferred_deferred_1_LDADD) $(LIBS) +deferred/deferred_2.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_2$(EXEEXT): $(deferred_deferred_2_OBJECTS) $(deferred_deferred_2_DEPENDENCIES) $(EXTRA_deferred_deferred_2_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_2$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_2_OBJECTS) $(deferred_deferred_2_LDADD) $(LIBS) echo/$(am__dirstamp): @$(MKDIR_P) echo @: > echo/$(am__dirstamp) @@ -1019,6 +1560,24 @@ executors/priority_scheduler.$(OBJEXT): executors/$(am__dirstamp) \ executors/priority_scheduler$(EXEEXT): $(executors_priority_scheduler_OBJECTS) $(executors_priority_scheduler_DEPENDENCIES) $(EXTRA_executors_priority_scheduler_DEPENDENCIES) executors/$(am__dirstamp) @rm -f executors/priority_scheduler$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(executors_priority_scheduler_OBJECTS) $(executors_priority_scheduler_LDADD) $(LIBS) +files/$(am__dirstamp): + @$(MKDIR_P) files + @: > files/$(am__dirstamp) +files/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) files/$(DEPDIR) + @: > files/$(DEPDIR)/$(am__dirstamp) +files/async_file_copy.$(OBJEXT): files/$(am__dirstamp) \ + files/$(DEPDIR)/$(am__dirstamp) + +files/async_file_copy$(EXEEXT): $(files_async_file_copy_OBJECTS) $(files_async_file_copy_DEPENDENCIES) $(EXTRA_files_async_file_copy_DEPENDENCIES) files/$(am__dirstamp) + @rm -f files/async_file_copy$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(files_async_file_copy_OBJECTS) $(files_async_file_copy_LDADD) $(LIBS) +files/blocking_file_copy.$(OBJEXT): files/$(am__dirstamp) \ + files/$(DEPDIR)/$(am__dirstamp) + +files/blocking_file_copy$(EXEEXT): $(files_blocking_file_copy_OBJECTS) $(files_blocking_file_copy_DEPENDENCIES) $(EXTRA_files_blocking_file_copy_DEPENDENCIES) files/$(am__dirstamp) + @rm -f files/blocking_file_copy$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(files_blocking_file_copy_OBJECTS) $(files_blocking_file_copy_LDADD) $(LIBS) fork/$(am__dirstamp): @$(MKDIR_P) fork @: > fork/$(am__dirstamp) @@ -1062,6 +1621,24 @@ handler_tracking/async_tcp_echo_server.$(OBJEXT): \ handler_tracking/async_tcp_echo_server$(EXEEXT): $(handler_tracking_async_tcp_echo_server_OBJECTS) $(handler_tracking_async_tcp_echo_server_DEPENDENCIES) $(EXTRA_handler_tracking_async_tcp_echo_server_DEPENDENCIES) handler_tracking/$(am__dirstamp) @rm -f handler_tracking/async_tcp_echo_server$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(handler_tracking_async_tcp_echo_server_OBJECTS) $(handler_tracking_async_tcp_echo_server_LDADD) $(LIBS) +http/client/$(am__dirstamp): + @$(MKDIR_P) http/client + @: > http/client/$(am__dirstamp) +http/client/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) http/client/$(DEPDIR) + @: > http/client/$(DEPDIR)/$(am__dirstamp) +http/client/async_client.$(OBJEXT): http/client/$(am__dirstamp) \ + http/client/$(DEPDIR)/$(am__dirstamp) + +http/client/async_client$(EXEEXT): $(http_client_async_client_OBJECTS) $(http_client_async_client_DEPENDENCIES) $(EXTRA_http_client_async_client_DEPENDENCIES) http/client/$(am__dirstamp) + @rm -f http/client/async_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(http_client_async_client_OBJECTS) $(http_client_async_client_LDADD) $(LIBS) +http/client/sync_client.$(OBJEXT): http/client/$(am__dirstamp) \ + http/client/$(DEPDIR)/$(am__dirstamp) + +http/client/sync_client$(EXEEXT): $(http_client_sync_client_OBJECTS) $(http_client_sync_client_DEPENDENCIES) $(EXTRA_http_client_sync_client_DEPENDENCIES) http/client/$(am__dirstamp) + @rm -f http/client/sync_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(http_client_sync_client_OBJECTS) $(http_client_sync_client_LDADD) $(LIBS) http/server/$(am__dirstamp): @$(MKDIR_P) http/server @: > http/server/$(am__dirstamp) @@ -1088,6 +1665,90 @@ http/server/server.$(OBJEXT): http/server/$(am__dirstamp) \ http/server/http_server$(EXEEXT): $(http_server_http_server_OBJECTS) $(http_server_http_server_DEPENDENCIES) $(EXTRA_http_server_http_server_DEPENDENCIES) http/server/$(am__dirstamp) @rm -f http/server/http_server$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(http_server_http_server_OBJECTS) $(http_server_http_server_LDADD) $(LIBS) +http/server2/$(am__dirstamp): + @$(MKDIR_P) http/server2 + @: > http/server2/$(am__dirstamp) +http/server2/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) http/server2/$(DEPDIR) + @: > http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/connection.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/io_context_pool.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/main.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/mime_types.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/reply.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/request_handler.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/request_parser.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) +http/server2/server.$(OBJEXT): http/server2/$(am__dirstamp) \ + http/server2/$(DEPDIR)/$(am__dirstamp) + +http/server2/http_server$(EXEEXT): $(http_server2_http_server_OBJECTS) $(http_server2_http_server_DEPENDENCIES) $(EXTRA_http_server2_http_server_DEPENDENCIES) http/server2/$(am__dirstamp) + @rm -f http/server2/http_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(http_server2_http_server_OBJECTS) $(http_server2_http_server_LDADD) $(LIBS) +http/server3/$(am__dirstamp): + @$(MKDIR_P) http/server3 + @: > http/server3/$(am__dirstamp) +http/server3/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) http/server3/$(DEPDIR) + @: > http/server3/$(DEPDIR)/$(am__dirstamp) +http/server3/connection.$(OBJEXT): http/server3/$(am__dirstamp) \ + http/server3/$(DEPDIR)/$(am__dirstamp) +http/server3/main.$(OBJEXT): http/server3/$(am__dirstamp) \ + http/server3/$(DEPDIR)/$(am__dirstamp) +http/server3/mime_types.$(OBJEXT): http/server3/$(am__dirstamp) \ + http/server3/$(DEPDIR)/$(am__dirstamp) +http/server3/reply.$(OBJEXT): http/server3/$(am__dirstamp) \ + http/server3/$(DEPDIR)/$(am__dirstamp) +http/server3/request_handler.$(OBJEXT): http/server3/$(am__dirstamp) \ + http/server3/$(DEPDIR)/$(am__dirstamp) +http/server3/request_parser.$(OBJEXT): http/server3/$(am__dirstamp) \ + http/server3/$(DEPDIR)/$(am__dirstamp) +http/server3/server.$(OBJEXT): http/server3/$(am__dirstamp) \ + http/server3/$(DEPDIR)/$(am__dirstamp) + +http/server3/http_server$(EXEEXT): $(http_server3_http_server_OBJECTS) $(http_server3_http_server_DEPENDENCIES) $(EXTRA_http_server3_http_server_DEPENDENCIES) http/server3/$(am__dirstamp) + @rm -f http/server3/http_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(http_server3_http_server_OBJECTS) $(http_server3_http_server_LDADD) $(LIBS) +http/server4/$(am__dirstamp): + @$(MKDIR_P) http/server4 + @: > http/server4/$(am__dirstamp) +http/server4/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) http/server4/$(DEPDIR) + @: > http/server4/$(DEPDIR)/$(am__dirstamp) +http/server4/file_handler.$(OBJEXT): http/server4/$(am__dirstamp) \ + http/server4/$(DEPDIR)/$(am__dirstamp) +http/server4/main.$(OBJEXT): http/server4/$(am__dirstamp) \ + http/server4/$(DEPDIR)/$(am__dirstamp) +http/server4/mime_types.$(OBJEXT): http/server4/$(am__dirstamp) \ + http/server4/$(DEPDIR)/$(am__dirstamp) +http/server4/reply.$(OBJEXT): http/server4/$(am__dirstamp) \ + http/server4/$(DEPDIR)/$(am__dirstamp) +http/server4/request_parser.$(OBJEXT): http/server4/$(am__dirstamp) \ + http/server4/$(DEPDIR)/$(am__dirstamp) +http/server4/server.$(OBJEXT): http/server4/$(am__dirstamp) \ + http/server4/$(DEPDIR)/$(am__dirstamp) + +http/server4/http_server$(EXEEXT): $(http_server4_http_server_OBJECTS) $(http_server4_http_server_DEPENDENCIES) $(EXTRA_http_server4_http_server_DEPENDENCIES) http/server4/$(am__dirstamp) + @rm -f http/server4/http_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(http_server4_http_server_OBJECTS) $(http_server4_http_server_LDADD) $(LIBS) +icmp/$(am__dirstamp): + @$(MKDIR_P) icmp + @: > icmp/$(am__dirstamp) +icmp/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) icmp/$(DEPDIR) + @: > icmp/$(DEPDIR)/$(am__dirstamp) +icmp/ping.$(OBJEXT): icmp/$(am__dirstamp) \ + icmp/$(DEPDIR)/$(am__dirstamp) + +icmp/ping$(EXEEXT): $(icmp_ping_OBJECTS) $(icmp_ping_DEPENDENCIES) $(EXTRA_icmp_ping_DEPENDENCIES) icmp/$(am__dirstamp) + @rm -f icmp/ping$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(icmp_ping_OBJECTS) $(icmp_ping_LDADD) $(LIBS) invocation/$(am__dirstamp): @$(MKDIR_P) invocation @: > invocation/$(am__dirstamp) @@ -1106,6 +1767,18 @@ iostreams/$(am__dirstamp): iostreams/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) iostreams/$(DEPDIR) @: > iostreams/$(DEPDIR)/$(am__dirstamp) +iostreams/daytime_client.$(OBJEXT): iostreams/$(am__dirstamp) \ + iostreams/$(DEPDIR)/$(am__dirstamp) + +iostreams/daytime_client$(EXEEXT): $(iostreams_daytime_client_OBJECTS) $(iostreams_daytime_client_DEPENDENCIES) $(EXTRA_iostreams_daytime_client_DEPENDENCIES) iostreams/$(am__dirstamp) + @rm -f iostreams/daytime_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(iostreams_daytime_client_OBJECTS) $(iostreams_daytime_client_LDADD) $(LIBS) +iostreams/daytime_server.$(OBJEXT): iostreams/$(am__dirstamp) \ + iostreams/$(DEPDIR)/$(am__dirstamp) + +iostreams/daytime_server$(EXEEXT): $(iostreams_daytime_server_OBJECTS) $(iostreams_daytime_server_DEPENDENCIES) $(EXTRA_iostreams_daytime_server_DEPENDENCIES) iostreams/$(am__dirstamp) + @rm -f iostreams/daytime_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(iostreams_daytime_server_OBJECTS) $(iostreams_daytime_server_LDADD) $(LIBS) iostreams/http_client.$(OBJEXT): iostreams/$(am__dirstamp) \ iostreams/$(DEPDIR)/$(am__dirstamp) @@ -1124,6 +1797,18 @@ local/connect_pair.$(OBJEXT): local/$(am__dirstamp) \ local/connect_pair$(EXEEXT): $(local_connect_pair_OBJECTS) $(local_connect_pair_DEPENDENCIES) $(EXTRA_local_connect_pair_DEPENDENCIES) local/$(am__dirstamp) @rm -f local/connect_pair$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(local_connect_pair_OBJECTS) $(local_connect_pair_LDADD) $(LIBS) +local/fd_passing_stream_client.$(OBJEXT): local/$(am__dirstamp) \ + local/$(DEPDIR)/$(am__dirstamp) + +local/fd_passing_stream_client$(EXEEXT): $(local_fd_passing_stream_client_OBJECTS) $(local_fd_passing_stream_client_DEPENDENCIES) $(EXTRA_local_fd_passing_stream_client_DEPENDENCIES) local/$(am__dirstamp) + @rm -f local/fd_passing_stream_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(local_fd_passing_stream_client_OBJECTS) $(local_fd_passing_stream_client_LDADD) $(LIBS) +local/fd_passing_stream_server.$(OBJEXT): local/$(am__dirstamp) \ + local/$(DEPDIR)/$(am__dirstamp) + +local/fd_passing_stream_server$(EXEEXT): $(local_fd_passing_stream_server_OBJECTS) $(local_fd_passing_stream_server_DEPENDENCIES) $(EXTRA_local_fd_passing_stream_server_DEPENDENCIES) local/$(am__dirstamp) + @rm -f local/fd_passing_stream_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(local_fd_passing_stream_server_OBJECTS) $(local_fd_passing_stream_server_LDADD) $(LIBS) local/iostream_client.$(OBJEXT): local/$(am__dirstamp) \ local/$(DEPDIR)/$(am__dirstamp) @@ -1226,6 +1911,77 @@ operations/composed_8.$(OBJEXT): operations/$(am__dirstamp) \ operations/composed_8$(EXEEXT): $(operations_composed_8_OBJECTS) $(operations_composed_8_DEPENDENCIES) $(EXTRA_operations_composed_8_DEPENDENCIES) operations/$(am__dirstamp) @rm -f operations/composed_8$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_8_OBJECTS) $(operations_composed_8_LDADD) $(LIBS) +parallel_group/$(am__dirstamp): + @$(MKDIR_P) parallel_group + @: > parallel_group/$(am__dirstamp) +parallel_group/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) parallel_group/$(DEPDIR) + @: > parallel_group/$(DEPDIR)/$(am__dirstamp) +parallel_group/ranged_wait_for_all.$(OBJEXT): \ + parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/ranged_wait_for_all$(EXEEXT): $(parallel_group_ranged_wait_for_all_OBJECTS) $(parallel_group_ranged_wait_for_all_DEPENDENCIES) $(EXTRA_parallel_group_ranged_wait_for_all_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/ranged_wait_for_all$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_ranged_wait_for_all_OBJECTS) $(parallel_group_ranged_wait_for_all_LDADD) $(LIBS) +parallel_group/wait_for_all.$(OBJEXT): parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_all$(EXEEXT): $(parallel_group_wait_for_all_OBJECTS) $(parallel_group_wait_for_all_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_all_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_all$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_all_OBJECTS) $(parallel_group_wait_for_all_LDADD) $(LIBS) +parallel_group/wait_for_one.$(OBJEXT): parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_one$(EXEEXT): $(parallel_group_wait_for_one_OBJECTS) $(parallel_group_wait_for_one_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_one_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_one$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_one_OBJECTS) $(parallel_group_wait_for_one_LDADD) $(LIBS) +parallel_group/wait_for_one_error.$(OBJEXT): \ + parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_one_error$(EXEEXT): $(parallel_group_wait_for_one_error_OBJECTS) $(parallel_group_wait_for_one_error_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_one_error_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_one_error$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_one_error_OBJECTS) $(parallel_group_wait_for_one_error_LDADD) $(LIBS) +parallel_group/wait_for_one_success.$(OBJEXT): \ + parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_one_success$(EXEEXT): $(parallel_group_wait_for_one_success_OBJECTS) $(parallel_group_wait_for_one_success_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_one_success_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_one_success$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_one_success_OBJECTS) $(parallel_group_wait_for_one_success_LDADD) $(LIBS) +porthopper/$(am__dirstamp): + @$(MKDIR_P) porthopper + @: > porthopper/$(am__dirstamp) +porthopper/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) porthopper/$(DEPDIR) + @: > porthopper/$(DEPDIR)/$(am__dirstamp) +porthopper/client.$(OBJEXT): porthopper/$(am__dirstamp) \ + porthopper/$(DEPDIR)/$(am__dirstamp) + +porthopper/client$(EXEEXT): $(porthopper_client_OBJECTS) $(porthopper_client_DEPENDENCIES) $(EXTRA_porthopper_client_DEPENDENCIES) porthopper/$(am__dirstamp) + @rm -f porthopper/client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(porthopper_client_OBJECTS) $(porthopper_client_LDADD) $(LIBS) +porthopper/server.$(OBJEXT): porthopper/$(am__dirstamp) \ + porthopper/$(DEPDIR)/$(am__dirstamp) + +porthopper/server$(EXEEXT): $(porthopper_server_OBJECTS) $(porthopper_server_DEPENDENCIES) $(EXTRA_porthopper_server_DEPENDENCIES) porthopper/$(am__dirstamp) + @rm -f porthopper/server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(porthopper_server_OBJECTS) $(porthopper_server_LDADD) $(LIBS) +services/$(am__dirstamp): + @$(MKDIR_P) services + @: > services/$(am__dirstamp) +services/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) services/$(DEPDIR) + @: > services/$(DEPDIR)/$(am__dirstamp) +services/daytime_client.$(OBJEXT): services/$(am__dirstamp) \ + services/$(DEPDIR)/$(am__dirstamp) +services/logger_service.$(OBJEXT): services/$(am__dirstamp) \ + services/$(DEPDIR)/$(am__dirstamp) + +services/daytime_client$(EXEEXT): $(services_daytime_client_OBJECTS) $(services_daytime_client_DEPENDENCIES) $(EXTRA_services_daytime_client_DEPENDENCIES) services/$(am__dirstamp) + @rm -f services/daytime_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(services_daytime_client_OBJECTS) $(services_daytime_client_LDADD) $(LIBS) socks4/$(am__dirstamp): @$(MKDIR_P) socks4 @: > socks4/$(am__dirstamp) @@ -1322,6 +2078,179 @@ timers/time_t_timer.$(OBJEXT): timers/$(am__dirstamp) \ timers/time_t_timer$(EXEEXT): $(timers_time_t_timer_OBJECTS) $(timers_time_t_timer_DEPENDENCIES) $(EXTRA_timers_time_t_timer_DEPENDENCIES) timers/$(am__dirstamp) @rm -f timers/time_t_timer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(timers_time_t_timer_OBJECTS) $(timers_time_t_timer_LDADD) $(LIBS) +tutorial/daytime1/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime1 + @: > tutorial/daytime1/$(am__dirstamp) +tutorial/daytime1/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime1/$(DEPDIR) + @: > tutorial/daytime1/$(DEPDIR)/$(am__dirstamp) +tutorial/daytime1/client.$(OBJEXT): tutorial/daytime1/$(am__dirstamp) \ + tutorial/daytime1/$(DEPDIR)/$(am__dirstamp) + +tutorial/daytime1/client$(EXEEXT): $(tutorial_daytime1_client_OBJECTS) $(tutorial_daytime1_client_DEPENDENCIES) $(EXTRA_tutorial_daytime1_client_DEPENDENCIES) tutorial/daytime1/$(am__dirstamp) + @rm -f tutorial/daytime1/client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_daytime1_client_OBJECTS) $(tutorial_daytime1_client_LDADD) $(LIBS) +tutorial/daytime2/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime2 + @: > tutorial/daytime2/$(am__dirstamp) +tutorial/daytime2/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime2/$(DEPDIR) + @: > tutorial/daytime2/$(DEPDIR)/$(am__dirstamp) +tutorial/daytime2/server.$(OBJEXT): tutorial/daytime2/$(am__dirstamp) \ + tutorial/daytime2/$(DEPDIR)/$(am__dirstamp) + +tutorial/daytime2/server$(EXEEXT): $(tutorial_daytime2_server_OBJECTS) $(tutorial_daytime2_server_DEPENDENCIES) $(EXTRA_tutorial_daytime2_server_DEPENDENCIES) tutorial/daytime2/$(am__dirstamp) + @rm -f tutorial/daytime2/server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_daytime2_server_OBJECTS) $(tutorial_daytime2_server_LDADD) $(LIBS) +tutorial/daytime3/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime3 + @: > tutorial/daytime3/$(am__dirstamp) +tutorial/daytime3/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime3/$(DEPDIR) + @: > tutorial/daytime3/$(DEPDIR)/$(am__dirstamp) +tutorial/daytime3/server.$(OBJEXT): tutorial/daytime3/$(am__dirstamp) \ + tutorial/daytime3/$(DEPDIR)/$(am__dirstamp) + +tutorial/daytime3/server$(EXEEXT): $(tutorial_daytime3_server_OBJECTS) $(tutorial_daytime3_server_DEPENDENCIES) $(EXTRA_tutorial_daytime3_server_DEPENDENCIES) tutorial/daytime3/$(am__dirstamp) + @rm -f tutorial/daytime3/server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_daytime3_server_OBJECTS) $(tutorial_daytime3_server_LDADD) $(LIBS) +tutorial/daytime4/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime4 + @: > tutorial/daytime4/$(am__dirstamp) +tutorial/daytime4/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime4/$(DEPDIR) + @: > tutorial/daytime4/$(DEPDIR)/$(am__dirstamp) +tutorial/daytime4/client.$(OBJEXT): tutorial/daytime4/$(am__dirstamp) \ + tutorial/daytime4/$(DEPDIR)/$(am__dirstamp) + +tutorial/daytime4/client$(EXEEXT): $(tutorial_daytime4_client_OBJECTS) $(tutorial_daytime4_client_DEPENDENCIES) $(EXTRA_tutorial_daytime4_client_DEPENDENCIES) tutorial/daytime4/$(am__dirstamp) + @rm -f tutorial/daytime4/client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_daytime4_client_OBJECTS) $(tutorial_daytime4_client_LDADD) $(LIBS) +tutorial/daytime5/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime5 + @: > tutorial/daytime5/$(am__dirstamp) +tutorial/daytime5/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime5/$(DEPDIR) + @: > tutorial/daytime5/$(DEPDIR)/$(am__dirstamp) +tutorial/daytime5/server.$(OBJEXT): tutorial/daytime5/$(am__dirstamp) \ + tutorial/daytime5/$(DEPDIR)/$(am__dirstamp) + +tutorial/daytime5/server$(EXEEXT): $(tutorial_daytime5_server_OBJECTS) $(tutorial_daytime5_server_DEPENDENCIES) $(EXTRA_tutorial_daytime5_server_DEPENDENCIES) tutorial/daytime5/$(am__dirstamp) + @rm -f tutorial/daytime5/server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_daytime5_server_OBJECTS) $(tutorial_daytime5_server_LDADD) $(LIBS) +tutorial/daytime6/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime6 + @: > tutorial/daytime6/$(am__dirstamp) +tutorial/daytime6/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime6/$(DEPDIR) + @: > tutorial/daytime6/$(DEPDIR)/$(am__dirstamp) +tutorial/daytime6/server.$(OBJEXT): tutorial/daytime6/$(am__dirstamp) \ + tutorial/daytime6/$(DEPDIR)/$(am__dirstamp) + +tutorial/daytime6/server$(EXEEXT): $(tutorial_daytime6_server_OBJECTS) $(tutorial_daytime6_server_DEPENDENCIES) $(EXTRA_tutorial_daytime6_server_DEPENDENCIES) tutorial/daytime6/$(am__dirstamp) + @rm -f tutorial/daytime6/server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_daytime6_server_OBJECTS) $(tutorial_daytime6_server_LDADD) $(LIBS) +tutorial/daytime7/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime7 + @: > tutorial/daytime7/$(am__dirstamp) +tutorial/daytime7/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/daytime7/$(DEPDIR) + @: > tutorial/daytime7/$(DEPDIR)/$(am__dirstamp) +tutorial/daytime7/server.$(OBJEXT): tutorial/daytime7/$(am__dirstamp) \ + tutorial/daytime7/$(DEPDIR)/$(am__dirstamp) + +tutorial/daytime7/server$(EXEEXT): $(tutorial_daytime7_server_OBJECTS) $(tutorial_daytime7_server_DEPENDENCIES) $(EXTRA_tutorial_daytime7_server_DEPENDENCIES) tutorial/daytime7/$(am__dirstamp) + @rm -f tutorial/daytime7/server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_daytime7_server_OBJECTS) $(tutorial_daytime7_server_LDADD) $(LIBS) +tutorial/timer1/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer1 + @: > tutorial/timer1/$(am__dirstamp) +tutorial/timer1/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer1/$(DEPDIR) + @: > tutorial/timer1/$(DEPDIR)/$(am__dirstamp) +tutorial/timer1/timer.$(OBJEXT): tutorial/timer1/$(am__dirstamp) \ + tutorial/timer1/$(DEPDIR)/$(am__dirstamp) + +tutorial/timer1/timer$(EXEEXT): $(tutorial_timer1_timer_OBJECTS) $(tutorial_timer1_timer_DEPENDENCIES) $(EXTRA_tutorial_timer1_timer_DEPENDENCIES) tutorial/timer1/$(am__dirstamp) + @rm -f tutorial/timer1/timer$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_timer1_timer_OBJECTS) $(tutorial_timer1_timer_LDADD) $(LIBS) +tutorial/timer2/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer2 + @: > tutorial/timer2/$(am__dirstamp) +tutorial/timer2/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer2/$(DEPDIR) + @: > tutorial/timer2/$(DEPDIR)/$(am__dirstamp) +tutorial/timer2/timer.$(OBJEXT): tutorial/timer2/$(am__dirstamp) \ + tutorial/timer2/$(DEPDIR)/$(am__dirstamp) + +tutorial/timer2/timer$(EXEEXT): $(tutorial_timer2_timer_OBJECTS) $(tutorial_timer2_timer_DEPENDENCIES) $(EXTRA_tutorial_timer2_timer_DEPENDENCIES) tutorial/timer2/$(am__dirstamp) + @rm -f tutorial/timer2/timer$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_timer2_timer_OBJECTS) $(tutorial_timer2_timer_LDADD) $(LIBS) +tutorial/timer3/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer3 + @: > tutorial/timer3/$(am__dirstamp) +tutorial/timer3/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer3/$(DEPDIR) + @: > tutorial/timer3/$(DEPDIR)/$(am__dirstamp) +tutorial/timer3/timer.$(OBJEXT): tutorial/timer3/$(am__dirstamp) \ + tutorial/timer3/$(DEPDIR)/$(am__dirstamp) + +tutorial/timer3/timer$(EXEEXT): $(tutorial_timer3_timer_OBJECTS) $(tutorial_timer3_timer_DEPENDENCIES) $(EXTRA_tutorial_timer3_timer_DEPENDENCIES) tutorial/timer3/$(am__dirstamp) + @rm -f tutorial/timer3/timer$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_timer3_timer_OBJECTS) $(tutorial_timer3_timer_LDADD) $(LIBS) +tutorial/timer4/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer4 + @: > tutorial/timer4/$(am__dirstamp) +tutorial/timer4/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer4/$(DEPDIR) + @: > tutorial/timer4/$(DEPDIR)/$(am__dirstamp) +tutorial/timer4/timer.$(OBJEXT): tutorial/timer4/$(am__dirstamp) \ + tutorial/timer4/$(DEPDIR)/$(am__dirstamp) + +tutorial/timer4/timer$(EXEEXT): $(tutorial_timer4_timer_OBJECTS) $(tutorial_timer4_timer_DEPENDENCIES) $(EXTRA_tutorial_timer4_timer_DEPENDENCIES) tutorial/timer4/$(am__dirstamp) + @rm -f tutorial/timer4/timer$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_timer4_timer_OBJECTS) $(tutorial_timer4_timer_LDADD) $(LIBS) +tutorial/timer5/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer5 + @: > tutorial/timer5/$(am__dirstamp) +tutorial/timer5/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tutorial/timer5/$(DEPDIR) + @: > tutorial/timer5/$(DEPDIR)/$(am__dirstamp) +tutorial/timer5/timer.$(OBJEXT): tutorial/timer5/$(am__dirstamp) \ + tutorial/timer5/$(DEPDIR)/$(am__dirstamp) + +tutorial/timer5/timer$(EXEEXT): $(tutorial_timer5_timer_OBJECTS) $(tutorial_timer5_timer_DEPENDENCIES) $(EXTRA_tutorial_timer5_timer_DEPENDENCIES) tutorial/timer5/$(am__dirstamp) + @rm -f tutorial/timer5/timer$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tutorial_timer5_timer_OBJECTS) $(tutorial_timer5_timer_LDADD) $(LIBS) +type_erasure/$(am__dirstamp): + @$(MKDIR_P) type_erasure + @: > type_erasure/$(am__dirstamp) +type_erasure/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) type_erasure/$(DEPDIR) + @: > type_erasure/$(DEPDIR)/$(am__dirstamp) +type_erasure/main.$(OBJEXT): type_erasure/$(am__dirstamp) \ + type_erasure/$(DEPDIR)/$(am__dirstamp) +type_erasure/stdin_line_reader.$(OBJEXT): \ + type_erasure/$(am__dirstamp) \ + type_erasure/$(DEPDIR)/$(am__dirstamp) +type_erasure/sleep.$(OBJEXT): type_erasure/$(am__dirstamp) \ + type_erasure/$(DEPDIR)/$(am__dirstamp) + +type_erasure/type_erasure$(EXEEXT): $(type_erasure_type_erasure_OBJECTS) $(type_erasure_type_erasure_DEPENDENCIES) $(EXTRA_type_erasure_type_erasure_DEPENDENCIES) type_erasure/$(am__dirstamp) + @rm -f type_erasure/type_erasure$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(type_erasure_type_erasure_OBJECTS) $(type_erasure_type_erasure_LDADD) $(LIBS) +windows/$(am__dirstamp): + @$(MKDIR_P) windows + @: > windows/$(am__dirstamp) +windows/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) windows/$(DEPDIR) + @: > windows/$(DEPDIR)/$(am__dirstamp) +windows/transmit_file.$(OBJEXT): windows/$(am__dirstamp) \ + windows/$(DEPDIR)/$(am__dirstamp) + +windows/transmit_file$(EXEEXT): $(windows_transmit_file_OBJECTS) $(windows_transmit_file_DEPENDENCIES) $(EXTRA_windows_transmit_file_DEPENDENCIES) windows/$(am__dirstamp) + @rm -f windows/transmit_file$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(windows_transmit_file_OBJECTS) $(windows_transmit_file_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -1329,23 +2258,47 @@ mostlyclean-compile: -rm -f allocation/*.$(OBJEXT) -rm -f buffers/*.$(OBJEXT) -rm -f chat/*.$(OBJEXT) + -rm -f deferred/*.$(OBJEXT) -rm -f echo/*.$(OBJEXT) -rm -f executors/*.$(OBJEXT) + -rm -f files/*.$(OBJEXT) -rm -f fork/*.$(OBJEXT) -rm -f futures/*.$(OBJEXT) -rm -f handler_tracking/*.$(OBJEXT) + -rm -f http/client/*.$(OBJEXT) -rm -f http/server/*.$(OBJEXT) + -rm -f http/server2/*.$(OBJEXT) + -rm -f http/server3/*.$(OBJEXT) + -rm -f http/server4/*.$(OBJEXT) + -rm -f icmp/*.$(OBJEXT) -rm -f invocation/*.$(OBJEXT) -rm -f iostreams/*.$(OBJEXT) -rm -f local/*.$(OBJEXT) -rm -f multicast/*.$(OBJEXT) -rm -f nonblocking/*.$(OBJEXT) -rm -f operations/*.$(OBJEXT) + -rm -f parallel_group/*.$(OBJEXT) + -rm -f porthopper/*.$(OBJEXT) + -rm -f services/*.$(OBJEXT) -rm -f socks4/*.$(OBJEXT) -rm -f spawn/*.$(OBJEXT) -rm -f ssl/*.$(OBJEXT) -rm -f timeouts/*.$(OBJEXT) -rm -f timers/*.$(OBJEXT) + -rm -f tutorial/daytime1/*.$(OBJEXT) + -rm -f tutorial/daytime2/*.$(OBJEXT) + -rm -f tutorial/daytime3/*.$(OBJEXT) + -rm -f tutorial/daytime4/*.$(OBJEXT) + -rm -f tutorial/daytime5/*.$(OBJEXT) + -rm -f tutorial/daytime6/*.$(OBJEXT) + -rm -f tutorial/daytime7/*.$(OBJEXT) + -rm -f tutorial/timer1/*.$(OBJEXT) + -rm -f tutorial/timer2/*.$(OBJEXT) + -rm -f tutorial/timer3/*.$(OBJEXT) + -rm -f tutorial/timer4/*.$(OBJEXT) + -rm -f tutorial/timer5/*.$(OBJEXT) + -rm -f type_erasure/*.$(OBJEXT) + -rm -f windows/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @@ -1356,6 +2309,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@buffers/$(DEPDIR)/reference_counted.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@chat/$(DEPDIR)/chat_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@chat/$(DEPDIR)/chat_server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@chat/$(DEPDIR)/posix_chat_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/async_tcp_echo_server.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/async_udp_echo_server.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/blocking_tcp_echo_client.Po@am__quote@ # am--include-marker @@ -1368,10 +2324,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/fork_join.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/pipeline.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/priority_scheduler.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@files/$(DEPDIR)/async_file_copy.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@files/$(DEPDIR)/blocking_file_copy.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@fork/$(DEPDIR)/daemon.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@fork/$(DEPDIR)/process_per_connection.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@futures/$(DEPDIR)/daytime_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@handler_tracking/$(DEPDIR)/async_tcp_echo_server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/client/$(DEPDIR)/async_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/client/$(DEPDIR)/sync_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@http/server/$(DEPDIR)/connection.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@http/server/$(DEPDIR)/connection_manager.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@http/server/$(DEPDIR)/main.Po@am__quote@ # am--include-marker @@ -1380,9 +2340,35 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@http/server/$(DEPDIR)/request_handler.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@http/server/$(DEPDIR)/request_parser.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@http/server/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/connection.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/io_context_pool.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/mime_types.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/reply.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/request_handler.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/request_parser.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server2/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server3/$(DEPDIR)/connection.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server3/$(DEPDIR)/main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server3/$(DEPDIR)/mime_types.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server3/$(DEPDIR)/reply.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server3/$(DEPDIR)/request_handler.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server3/$(DEPDIR)/request_parser.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server3/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server4/$(DEPDIR)/file_handler.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server4/$(DEPDIR)/main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server4/$(DEPDIR)/mime_types.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server4/$(DEPDIR)/reply.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server4/$(DEPDIR)/request_parser.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@http/server4/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@icmp/$(DEPDIR)/ping.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@invocation/$(DEPDIR)/prioritised_handlers.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@iostreams/$(DEPDIR)/daytime_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@iostreams/$(DEPDIR)/daytime_server.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@iostreams/$(DEPDIR)/http_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@local/$(DEPDIR)/connect_pair.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@local/$(DEPDIR)/fd_passing_stream_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@local/$(DEPDIR)/fd_passing_stream_server.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@local/$(DEPDIR)/iostream_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@local/$(DEPDIR)/stream_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@local/$(DEPDIR)/stream_server.Po@am__quote@ # am--include-marker @@ -1397,6 +2383,15 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_6.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_7.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_8.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/ranged_wait_for_all.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_all.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_one.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_one_error.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_one_success.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@porthopper/$(DEPDIR)/client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@porthopper/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@services/$(DEPDIR)/daytime_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@services/$(DEPDIR)/logger_service.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@socks4/$(DEPDIR)/sync_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@spawn/$(DEPDIR)/echo_server.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@spawn/$(DEPDIR)/parallel_grep.Po@am__quote@ # am--include-marker @@ -1408,6 +2403,22 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@timeouts/$(DEPDIR)/blocking_udp_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@timeouts/$(DEPDIR)/server.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@timers/$(DEPDIR)/time_t_timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/daytime1/$(DEPDIR)/client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/daytime2/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/daytime3/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/daytime4/$(DEPDIR)/client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/daytime5/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/daytime6/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/daytime7/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/timer1/$(DEPDIR)/timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/timer2/$(DEPDIR)/timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/timer3/$(DEPDIR)/timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/timer4/$(DEPDIR)/timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tutorial/timer5/$(DEPDIR)/timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@type_erasure/$(DEPDIR)/main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@type_erasure/$(DEPDIR)/sleep.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@type_erasure/$(DEPDIR)/stdin_line_reader.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@windows/$(DEPDIR)/transmit_file.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -1482,7 +2493,6 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -1554,18 +2564,32 @@ distclean-generic: -rm -f buffers/$(am__dirstamp) -rm -f chat/$(DEPDIR)/$(am__dirstamp) -rm -f chat/$(am__dirstamp) + -rm -f deferred/$(DEPDIR)/$(am__dirstamp) + -rm -f deferred/$(am__dirstamp) -rm -f echo/$(DEPDIR)/$(am__dirstamp) -rm -f echo/$(am__dirstamp) -rm -f executors/$(DEPDIR)/$(am__dirstamp) -rm -f executors/$(am__dirstamp) + -rm -f files/$(DEPDIR)/$(am__dirstamp) + -rm -f files/$(am__dirstamp) -rm -f fork/$(DEPDIR)/$(am__dirstamp) -rm -f fork/$(am__dirstamp) -rm -f futures/$(DEPDIR)/$(am__dirstamp) -rm -f futures/$(am__dirstamp) -rm -f handler_tracking/$(DEPDIR)/$(am__dirstamp) -rm -f handler_tracking/$(am__dirstamp) + -rm -f http/client/$(DEPDIR)/$(am__dirstamp) + -rm -f http/client/$(am__dirstamp) -rm -f http/server/$(DEPDIR)/$(am__dirstamp) -rm -f http/server/$(am__dirstamp) + -rm -f http/server2/$(DEPDIR)/$(am__dirstamp) + -rm -f http/server2/$(am__dirstamp) + -rm -f http/server3/$(DEPDIR)/$(am__dirstamp) + -rm -f http/server3/$(am__dirstamp) + -rm -f http/server4/$(DEPDIR)/$(am__dirstamp) + -rm -f http/server4/$(am__dirstamp) + -rm -f icmp/$(DEPDIR)/$(am__dirstamp) + -rm -f icmp/$(am__dirstamp) -rm -f invocation/$(DEPDIR)/$(am__dirstamp) -rm -f invocation/$(am__dirstamp) -rm -f iostreams/$(DEPDIR)/$(am__dirstamp) @@ -1578,6 +2602,12 @@ distclean-generic: -rm -f nonblocking/$(am__dirstamp) -rm -f operations/$(DEPDIR)/$(am__dirstamp) -rm -f operations/$(am__dirstamp) + -rm -f parallel_group/$(DEPDIR)/$(am__dirstamp) + -rm -f parallel_group/$(am__dirstamp) + -rm -f porthopper/$(DEPDIR)/$(am__dirstamp) + -rm -f porthopper/$(am__dirstamp) + -rm -f services/$(DEPDIR)/$(am__dirstamp) + -rm -f services/$(am__dirstamp) -rm -f socks4/$(DEPDIR)/$(am__dirstamp) -rm -f socks4/$(am__dirstamp) -rm -f spawn/$(DEPDIR)/$(am__dirstamp) @@ -1588,6 +2618,34 @@ distclean-generic: -rm -f timeouts/$(am__dirstamp) -rm -f timers/$(DEPDIR)/$(am__dirstamp) -rm -f timers/$(am__dirstamp) + -rm -f tutorial/daytime1/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/daytime1/$(am__dirstamp) + -rm -f tutorial/daytime2/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/daytime2/$(am__dirstamp) + -rm -f tutorial/daytime3/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/daytime3/$(am__dirstamp) + -rm -f tutorial/daytime4/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/daytime4/$(am__dirstamp) + -rm -f tutorial/daytime5/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/daytime5/$(am__dirstamp) + -rm -f tutorial/daytime6/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/daytime6/$(am__dirstamp) + -rm -f tutorial/daytime7/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/daytime7/$(am__dirstamp) + -rm -f tutorial/timer1/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/timer1/$(am__dirstamp) + -rm -f tutorial/timer2/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/timer2/$(am__dirstamp) + -rm -f tutorial/timer3/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/timer3/$(am__dirstamp) + -rm -f tutorial/timer4/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/timer4/$(am__dirstamp) + -rm -f tutorial/timer5/$(DEPDIR)/$(am__dirstamp) + -rm -f tutorial/timer5/$(am__dirstamp) + -rm -f type_erasure/$(DEPDIR)/$(am__dirstamp) + -rm -f type_erasure/$(am__dirstamp) + -rm -f windows/$(DEPDIR)/$(am__dirstamp) + -rm -f windows/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -1605,6 +2663,9 @@ distclean: distclean-am -rm -f buffers/$(DEPDIR)/reference_counted.Po -rm -f chat/$(DEPDIR)/chat_client.Po -rm -f chat/$(DEPDIR)/chat_server.Po + -rm -f chat/$(DEPDIR)/posix_chat_client.Po + -rm -f deferred/$(DEPDIR)/deferred_1.Po + -rm -f deferred/$(DEPDIR)/deferred_2.Po -rm -f echo/$(DEPDIR)/async_tcp_echo_server.Po -rm -f echo/$(DEPDIR)/async_udp_echo_server.Po -rm -f echo/$(DEPDIR)/blocking_tcp_echo_client.Po @@ -1617,10 +2678,14 @@ distclean: distclean-am -rm -f executors/$(DEPDIR)/fork_join.Po -rm -f executors/$(DEPDIR)/pipeline.Po -rm -f executors/$(DEPDIR)/priority_scheduler.Po + -rm -f files/$(DEPDIR)/async_file_copy.Po + -rm -f files/$(DEPDIR)/blocking_file_copy.Po -rm -f fork/$(DEPDIR)/daemon.Po -rm -f fork/$(DEPDIR)/process_per_connection.Po -rm -f futures/$(DEPDIR)/daytime_client.Po -rm -f handler_tracking/$(DEPDIR)/async_tcp_echo_server.Po + -rm -f http/client/$(DEPDIR)/async_client.Po + -rm -f http/client/$(DEPDIR)/sync_client.Po -rm -f http/server/$(DEPDIR)/connection.Po -rm -f http/server/$(DEPDIR)/connection_manager.Po -rm -f http/server/$(DEPDIR)/main.Po @@ -1629,9 +2694,35 @@ distclean: distclean-am -rm -f http/server/$(DEPDIR)/request_handler.Po -rm -f http/server/$(DEPDIR)/request_parser.Po -rm -f http/server/$(DEPDIR)/server.Po + -rm -f http/server2/$(DEPDIR)/connection.Po + -rm -f http/server2/$(DEPDIR)/io_context_pool.Po + -rm -f http/server2/$(DEPDIR)/main.Po + -rm -f http/server2/$(DEPDIR)/mime_types.Po + -rm -f http/server2/$(DEPDIR)/reply.Po + -rm -f http/server2/$(DEPDIR)/request_handler.Po + -rm -f http/server2/$(DEPDIR)/request_parser.Po + -rm -f http/server2/$(DEPDIR)/server.Po + -rm -f http/server3/$(DEPDIR)/connection.Po + -rm -f http/server3/$(DEPDIR)/main.Po + -rm -f http/server3/$(DEPDIR)/mime_types.Po + -rm -f http/server3/$(DEPDIR)/reply.Po + -rm -f http/server3/$(DEPDIR)/request_handler.Po + -rm -f http/server3/$(DEPDIR)/request_parser.Po + -rm -f http/server3/$(DEPDIR)/server.Po + -rm -f http/server4/$(DEPDIR)/file_handler.Po + -rm -f http/server4/$(DEPDIR)/main.Po + -rm -f http/server4/$(DEPDIR)/mime_types.Po + -rm -f http/server4/$(DEPDIR)/reply.Po + -rm -f http/server4/$(DEPDIR)/request_parser.Po + -rm -f http/server4/$(DEPDIR)/server.Po + -rm -f icmp/$(DEPDIR)/ping.Po -rm -f invocation/$(DEPDIR)/prioritised_handlers.Po + -rm -f iostreams/$(DEPDIR)/daytime_client.Po + -rm -f iostreams/$(DEPDIR)/daytime_server.Po -rm -f iostreams/$(DEPDIR)/http_client.Po -rm -f local/$(DEPDIR)/connect_pair.Po + -rm -f local/$(DEPDIR)/fd_passing_stream_client.Po + -rm -f local/$(DEPDIR)/fd_passing_stream_server.Po -rm -f local/$(DEPDIR)/iostream_client.Po -rm -f local/$(DEPDIR)/stream_client.Po -rm -f local/$(DEPDIR)/stream_server.Po @@ -1646,6 +2737,15 @@ distclean: distclean-am -rm -f operations/$(DEPDIR)/composed_6.Po -rm -f operations/$(DEPDIR)/composed_7.Po -rm -f operations/$(DEPDIR)/composed_8.Po + -rm -f parallel_group/$(DEPDIR)/ranged_wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_error.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_success.Po + -rm -f porthopper/$(DEPDIR)/client.Po + -rm -f porthopper/$(DEPDIR)/server.Po + -rm -f services/$(DEPDIR)/daytime_client.Po + -rm -f services/$(DEPDIR)/logger_service.Po -rm -f socks4/$(DEPDIR)/sync_client.Po -rm -f spawn/$(DEPDIR)/echo_server.Po -rm -f spawn/$(DEPDIR)/parallel_grep.Po @@ -1657,6 +2757,22 @@ distclean: distclean-am -rm -f timeouts/$(DEPDIR)/blocking_udp_client.Po -rm -f timeouts/$(DEPDIR)/server.Po -rm -f timers/$(DEPDIR)/time_t_timer.Po + -rm -f tutorial/daytime1/$(DEPDIR)/client.Po + -rm -f tutorial/daytime2/$(DEPDIR)/server.Po + -rm -f tutorial/daytime3/$(DEPDIR)/server.Po + -rm -f tutorial/daytime4/$(DEPDIR)/client.Po + -rm -f tutorial/daytime5/$(DEPDIR)/server.Po + -rm -f tutorial/daytime6/$(DEPDIR)/server.Po + -rm -f tutorial/daytime7/$(DEPDIR)/server.Po + -rm -f tutorial/timer1/$(DEPDIR)/timer.Po + -rm -f tutorial/timer2/$(DEPDIR)/timer.Po + -rm -f tutorial/timer3/$(DEPDIR)/timer.Po + -rm -f tutorial/timer4/$(DEPDIR)/timer.Po + -rm -f tutorial/timer5/$(DEPDIR)/timer.Po + -rm -f type_erasure/$(DEPDIR)/main.Po + -rm -f type_erasure/$(DEPDIR)/sleep.Po + -rm -f type_erasure/$(DEPDIR)/stdin_line_reader.Po + -rm -f windows/$(DEPDIR)/transmit_file.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1708,6 +2824,9 @@ maintainer-clean: maintainer-clean-am -rm -f buffers/$(DEPDIR)/reference_counted.Po -rm -f chat/$(DEPDIR)/chat_client.Po -rm -f chat/$(DEPDIR)/chat_server.Po + -rm -f chat/$(DEPDIR)/posix_chat_client.Po + -rm -f deferred/$(DEPDIR)/deferred_1.Po + -rm -f deferred/$(DEPDIR)/deferred_2.Po -rm -f echo/$(DEPDIR)/async_tcp_echo_server.Po -rm -f echo/$(DEPDIR)/async_udp_echo_server.Po -rm -f echo/$(DEPDIR)/blocking_tcp_echo_client.Po @@ -1720,10 +2839,14 @@ maintainer-clean: maintainer-clean-am -rm -f executors/$(DEPDIR)/fork_join.Po -rm -f executors/$(DEPDIR)/pipeline.Po -rm -f executors/$(DEPDIR)/priority_scheduler.Po + -rm -f files/$(DEPDIR)/async_file_copy.Po + -rm -f files/$(DEPDIR)/blocking_file_copy.Po -rm -f fork/$(DEPDIR)/daemon.Po -rm -f fork/$(DEPDIR)/process_per_connection.Po -rm -f futures/$(DEPDIR)/daytime_client.Po -rm -f handler_tracking/$(DEPDIR)/async_tcp_echo_server.Po + -rm -f http/client/$(DEPDIR)/async_client.Po + -rm -f http/client/$(DEPDIR)/sync_client.Po -rm -f http/server/$(DEPDIR)/connection.Po -rm -f http/server/$(DEPDIR)/connection_manager.Po -rm -f http/server/$(DEPDIR)/main.Po @@ -1732,9 +2855,35 @@ maintainer-clean: maintainer-clean-am -rm -f http/server/$(DEPDIR)/request_handler.Po -rm -f http/server/$(DEPDIR)/request_parser.Po -rm -f http/server/$(DEPDIR)/server.Po + -rm -f http/server2/$(DEPDIR)/connection.Po + -rm -f http/server2/$(DEPDIR)/io_context_pool.Po + -rm -f http/server2/$(DEPDIR)/main.Po + -rm -f http/server2/$(DEPDIR)/mime_types.Po + -rm -f http/server2/$(DEPDIR)/reply.Po + -rm -f http/server2/$(DEPDIR)/request_handler.Po + -rm -f http/server2/$(DEPDIR)/request_parser.Po + -rm -f http/server2/$(DEPDIR)/server.Po + -rm -f http/server3/$(DEPDIR)/connection.Po + -rm -f http/server3/$(DEPDIR)/main.Po + -rm -f http/server3/$(DEPDIR)/mime_types.Po + -rm -f http/server3/$(DEPDIR)/reply.Po + -rm -f http/server3/$(DEPDIR)/request_handler.Po + -rm -f http/server3/$(DEPDIR)/request_parser.Po + -rm -f http/server3/$(DEPDIR)/server.Po + -rm -f http/server4/$(DEPDIR)/file_handler.Po + -rm -f http/server4/$(DEPDIR)/main.Po + -rm -f http/server4/$(DEPDIR)/mime_types.Po + -rm -f http/server4/$(DEPDIR)/reply.Po + -rm -f http/server4/$(DEPDIR)/request_parser.Po + -rm -f http/server4/$(DEPDIR)/server.Po + -rm -f icmp/$(DEPDIR)/ping.Po -rm -f invocation/$(DEPDIR)/prioritised_handlers.Po + -rm -f iostreams/$(DEPDIR)/daytime_client.Po + -rm -f iostreams/$(DEPDIR)/daytime_server.Po -rm -f iostreams/$(DEPDIR)/http_client.Po -rm -f local/$(DEPDIR)/connect_pair.Po + -rm -f local/$(DEPDIR)/fd_passing_stream_client.Po + -rm -f local/$(DEPDIR)/fd_passing_stream_server.Po -rm -f local/$(DEPDIR)/iostream_client.Po -rm -f local/$(DEPDIR)/stream_client.Po -rm -f local/$(DEPDIR)/stream_server.Po @@ -1749,6 +2898,15 @@ maintainer-clean: maintainer-clean-am -rm -f operations/$(DEPDIR)/composed_6.Po -rm -f operations/$(DEPDIR)/composed_7.Po -rm -f operations/$(DEPDIR)/composed_8.Po + -rm -f parallel_group/$(DEPDIR)/ranged_wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_error.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_success.Po + -rm -f porthopper/$(DEPDIR)/client.Po + -rm -f porthopper/$(DEPDIR)/server.Po + -rm -f services/$(DEPDIR)/daytime_client.Po + -rm -f services/$(DEPDIR)/logger_service.Po -rm -f socks4/$(DEPDIR)/sync_client.Po -rm -f spawn/$(DEPDIR)/echo_server.Po -rm -f spawn/$(DEPDIR)/parallel_grep.Po @@ -1760,6 +2918,22 @@ maintainer-clean: maintainer-clean-am -rm -f timeouts/$(DEPDIR)/blocking_udp_client.Po -rm -f timeouts/$(DEPDIR)/server.Po -rm -f timers/$(DEPDIR)/time_t_timer.Po + -rm -f tutorial/daytime1/$(DEPDIR)/client.Po + -rm -f tutorial/daytime2/$(DEPDIR)/server.Po + -rm -f tutorial/daytime3/$(DEPDIR)/server.Po + -rm -f tutorial/daytime4/$(DEPDIR)/client.Po + -rm -f tutorial/daytime5/$(DEPDIR)/server.Po + -rm -f tutorial/daytime6/$(DEPDIR)/server.Po + -rm -f tutorial/daytime7/$(DEPDIR)/server.Po + -rm -f tutorial/timer1/$(DEPDIR)/timer.Po + -rm -f tutorial/timer2/$(DEPDIR)/timer.Po + -rm -f tutorial/timer3/$(DEPDIR)/timer.Po + -rm -f tutorial/timer4/$(DEPDIR)/timer.Po + -rm -f tutorial/timer5/$(DEPDIR)/timer.Po + -rm -f type_erasure/$(DEPDIR)/main.Po + -rm -f type_erasure/$(DEPDIR)/sleep.Po + -rm -f type_erasure/$(DEPDIR)/stdin_line_reader.Po + -rm -f windows/$(DEPDIR)/transmit_file.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/3rdparty/asio/src/examples/cpp11/allocation/server.cpp b/3rdparty/asio/src/examples/cpp11/allocation/server.cpp index 4d0d80e6875..48bc119c1c5 100644 --- a/3rdparty/asio/src/examples/cpp11/allocation/server.cpp +++ b/3rdparty/asio/src/examples/cpp11/allocation/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -112,46 +112,6 @@ private: handler_memory& memory_; }; -// Wrapper class template for handler objects to allow handler memory -// allocation to be customised. The allocator_type type and get_allocator() -// member function are used by the asynchronous operations to obtain the -// allocator. Calls to operator() are forwarded to the encapsulated handler. -template <typename Handler> -class custom_alloc_handler -{ -public: - using allocator_type = handler_allocator<Handler>; - - custom_alloc_handler(handler_memory& m, Handler h) - : memory_(m), - handler_(h) - { - } - - allocator_type get_allocator() const noexcept - { - return allocator_type(memory_); - } - - template <typename ...Args> - void operator()(Args&&... args) - { - handler_(std::forward<Args>(args)...); - } - -private: - handler_memory& memory_; - Handler handler_; -}; - -// Helper function to wrap a handler object to add custom allocation. -template <typename Handler> -inline custom_alloc_handler<Handler> make_custom_alloc_handler( - handler_memory& m, Handler h) -{ - return custom_alloc_handler<Handler>(m, h); -} - class session : public std::enable_shared_from_this<session> { @@ -171,7 +131,8 @@ private: { auto self(shared_from_this()); socket_.async_read_some(asio::buffer(data_), - make_custom_alloc_handler(handler_memory_, + asio::bind_allocator( + handler_allocator<int>(handler_memory_), [this, self](std::error_code ec, std::size_t length) { if (!ec) @@ -185,7 +146,8 @@ private: { auto self(shared_from_this()); asio::async_write(socket_, asio::buffer(data_, length), - make_custom_alloc_handler(handler_memory_, + asio::bind_allocator( + handler_allocator<int>(handler_memory_), [this, self](std::error_code ec, std::size_t /*length*/) { if (!ec) diff --git a/3rdparty/asio/src/examples/cpp11/buffers/reference_counted.cpp b/3rdparty/asio/src/examples/cpp11/buffers/reference_counted.cpp index d0f565faf66..cee56ff786b 100644 --- a/3rdparty/asio/src/examples/cpp11/buffers/reference_counted.cpp +++ b/3rdparty/asio/src/examples/cpp11/buffers/reference_counted.cpp @@ -2,7 +2,7 @@ // reference_counted.cpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/chat/chat_client.cpp b/3rdparty/asio/src/examples/cpp11/chat/chat_client.cpp index 6280851a82e..c0393ee8266 100644 --- a/3rdparty/asio/src/examples/cpp11/chat/chat_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/chat/chat_client.cpp @@ -2,7 +2,7 @@ // chat_client.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/chat/chat_message.hpp b/3rdparty/asio/src/examples/cpp11/chat/chat_message.hpp index cdc09ea33f8..2ae82fa1257 100644 --- a/3rdparty/asio/src/examples/cpp11/chat/chat_message.hpp +++ b/3rdparty/asio/src/examples/cpp11/chat/chat_message.hpp @@ -2,7 +2,7 @@ // chat_message.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -18,8 +18,8 @@ class chat_message { public: - enum { header_length = 4 }; - enum { max_body_length = 512 }; + static constexpr std::size_t header_length = 4; + static constexpr std::size_t max_body_length = 512; chat_message() : body_length_(0) diff --git a/3rdparty/asio/src/examples/cpp11/chat/chat_server.cpp b/3rdparty/asio/src/examples/cpp11/chat/chat_server.cpp index edc7b44cd6a..7a5dfe33d4f 100644 --- a/3rdparty/asio/src/examples/cpp11/chat/chat_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/chat/chat_server.cpp @@ -2,7 +2,7 @@ // chat_server.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/chat/posix_chat_client.cpp b/3rdparty/asio/src/examples/cpp11/chat/posix_chat_client.cpp new file mode 100644 index 00000000000..a77b8cfb001 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/chat/posix_chat_client.cpp @@ -0,0 +1,198 @@ +// +// posix_chat_client.cpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <array> +#include <cstdlib> +#include <cstring> +#include <iostream> +#include "asio.hpp" +#include "chat_message.hpp" + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +using asio::ip::tcp; +namespace posix = asio::posix; + +class posix_chat_client +{ +public: + posix_chat_client(asio::io_context& io_context, + const tcp::resolver::results_type& endpoints) + : socket_(io_context), + input_(io_context, ::dup(STDIN_FILENO)), + output_(io_context, ::dup(STDOUT_FILENO)), + input_buffer_(chat_message::max_body_length) + { + do_connect(endpoints); + } + +private: + void do_connect(const tcp::resolver::results_type& endpoints) + { + asio::async_connect(socket_, endpoints, + [this](std::error_code ec, tcp::endpoint) + { + if (!ec) + { + do_read_header(); + do_read_input(); + } + }); + } + + void do_read_header() + { + asio::async_read(socket_, + asio::buffer(read_msg_.data(), chat_message::header_length), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec && read_msg_.decode_header()) + { + do_read_body(); + } + else + { + close(); + } + }); + } + + void do_read_body() + { + asio::async_read(socket_, + asio::buffer(read_msg_.body(), read_msg_.body_length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + do_write_output(); + } + else + { + close(); + } + }); + } + + void do_write_output() + { + // Write out the message we just received, terminated by a newline. + static char eol[] = { '\n' }; + std::array<asio::const_buffer, 2> buffers = {{ + asio::buffer(read_msg_.body(), read_msg_.body_length()), + asio::buffer(eol) }}; + asio::async_write(output_, buffers, + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + do_read_header(); + } + else + { + close(); + } + }); + } + + void do_read_input() + { + // Read a line of input entered by the user. + asio::async_read_until(input_, input_buffer_, '\n', + [this](std::error_code ec, std::size_t length) + { + if (!ec) + { + // Write the message (minus the newline) to the server. + write_msg_.body_length(length - 1); + input_buffer_.sgetn(write_msg_.body(), length - 1); + input_buffer_.consume(1); // Remove newline from input. + write_msg_.encode_header(); + do_write_message(); + } + else if (ec == asio::error::not_found) + { + // Didn't get a newline. Send whatever we have. + write_msg_.body_length(input_buffer_.size()); + input_buffer_.sgetn(write_msg_.body(), input_buffer_.size()); + write_msg_.encode_header(); + do_write_message(); + } + else + { + close(); + } + }); + } + + void do_write_message() + { + asio::async_write(socket_, + asio::buffer(write_msg_.data(), write_msg_.length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + do_read_input(); + } + else + { + close(); + } + }); + } + + void close() + { + // Cancel all outstanding asynchronous operations. + socket_.close(); + input_.close(); + output_.close(); + } + +private: + tcp::socket socket_; + posix::stream_descriptor input_; + posix::stream_descriptor output_; + chat_message read_msg_; + chat_message write_msg_; + asio::streambuf input_buffer_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cerr << "Usage: posix_chat_client <host> <port>\n"; + return 1; + } + + asio::io_context io_context; + + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]); + + posix_chat_client c(io_context, endpoints); + + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp11/deferred/deferred_1.cpp b/3rdparty/asio/src/examples/cpp11/deferred/deferred_1.cpp new file mode 100644 index 00000000000..db9213eb3be --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/deferred/deferred_1.cpp @@ -0,0 +1,35 @@ +// +// deferred_1.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <iostream> + +using asio::deferred; + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + auto deferred_op = timer.async_wait(deferred); + + std::move(deferred_op)( + [](std::error_code ec) + { + std::cout << "timer wait finished: " << ec.message() << "\n"; + } + ); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/deferred/deferred_2.cpp b/3rdparty/asio/src/examples/cpp11/deferred/deferred_2.cpp new file mode 100644 index 00000000000..07528282de5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/deferred/deferred_2.cpp @@ -0,0 +1,44 @@ +// +// deferred_2.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <iostream> + +using asio::deferred; + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + auto deferred_op = timer.async_wait( + deferred( + [&](std::error_code ec) + { + std::cout << "first timer wait finished: " << ec.message() << "\n"; + timer.expires_after(std::chrono::seconds(1)); + return timer.async_wait(deferred); + } + ) + ); + + std::move(deferred_op)( + [](std::error_code ec) + { + std::cout << "second timer wait finished: " << ec.message() << "\n"; + } + ); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp b/3rdparty/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp index 0f776cca718..b8ba5337697 100644 --- a/3rdparty/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // async_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/echo/async_udp_echo_server.cpp b/3rdparty/asio/src/examples/cpp11/echo/async_udp_echo_server.cpp index d09c939f72d..8e5c26fba2a 100644 --- a/3rdparty/asio/src/examples/cpp11/echo/async_udp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/echo/async_udp_echo_server.cpp @@ -2,7 +2,7 @@ // async_udp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_client.cpp b/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_client.cpp index 96a843e41ad..8a281203f89 100644 --- a/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_client.cpp @@ -2,7 +2,7 @@ // blocking_tcp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp b/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp index d772b5a6bf1..34e5f221695 100644 --- a/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // blocking_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -26,12 +26,12 @@ void session(tcp::socket sock) { char data[max_length]; - asio::error_code error; + std::error_code error; size_t length = sock.read_some(asio::buffer(data), error); if (error == asio::error::eof) break; // Connection closed cleanly by peer. else if (error) - throw asio::system_error(error); // Some other error. + throw std::system_error(error); // Some other error. asio::write(sock, asio::buffer(data, length)); } diff --git a/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_client.cpp b/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_client.cpp index 11a6c9258bd..3f2b60e3ccc 100644 --- a/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_client.cpp @@ -2,7 +2,7 @@ // blocking_udp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_server.cpp b/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_server.cpp index 7cf8920ec97..64c6defb885 100644 --- a/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/echo/blocking_udp_echo_server.cpp @@ -2,7 +2,7 @@ // blocking_udp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/executors/bank_account_1.cpp b/3rdparty/asio/src/examples/cpp11/executors/bank_account_1.cpp index abfd16a7ee0..a63d7fc059b 100644 --- a/3rdparty/asio/src/examples/cpp11/executors/bank_account_1.cpp +++ b/3rdparty/asio/src/examples/cpp11/executors/bank_account_1.cpp @@ -16,8 +16,7 @@ class bank_account public: void deposit(int amount) { - execution::execute( - pool_.executor(), + pool_.executor().execute( [this, amount] { balance_ += amount; @@ -26,8 +25,7 @@ public: void withdraw(int amount) { - execution::execute( - pool_.executor(), + pool_.executor().execute( [this, amount] { if (balance_ >= amount) @@ -37,8 +35,7 @@ public: void print_balance() const { - execution::execute( - pool_.executor(), + pool_.executor().execute( [this] { std::cout << "balance = " << balance_ << "\n"; diff --git a/3rdparty/asio/src/examples/cpp11/executors/bank_account_2.cpp b/3rdparty/asio/src/examples/cpp11/executors/bank_account_2.cpp index 305d0ca5b86..45a24abc352 100644 --- a/3rdparty/asio/src/examples/cpp11/executors/bank_account_2.cpp +++ b/3rdparty/asio/src/examples/cpp11/executors/bank_account_2.cpp @@ -16,9 +16,7 @@ class bank_account public: void deposit(int amount) { - execution::execute( - asio::require(pool_.executor(), - execution::blocking.always), + asio::require(pool_.executor(), execution::blocking.always).execute( [this, amount] { balance_ += amount; @@ -27,9 +25,7 @@ public: void withdraw(int amount) { - execution::execute( - asio::require(pool_.executor(), - execution::blocking.always), + asio::require(pool_.executor(), execution::blocking.always).execute( [this, amount] { if (balance_ >= amount) @@ -40,9 +36,7 @@ public: int balance() const { int result = 0; - execution::execute( - asio::require(pool_.executor(), - execution::blocking.always), + asio::require(pool_.executor(), execution::blocking.always).execute( [this, &result] { result = balance_; diff --git a/3rdparty/asio/src/examples/cpp11/executors/fork_join.cpp b/3rdparty/asio/src/examples/cpp11/executors/fork_join.cpp index a76437efad9..7e8a827356d 100644 --- a/3rdparty/asio/src/examples/cpp11/executors/fork_join.cpp +++ b/3rdparty/asio/src/examples/cpp11/executors/fork_join.cpp @@ -32,8 +32,7 @@ public: // it is time to shut down, i.e. the use count is zero. for (thread_count_ = 0; thread_count_ < thread_count; ++thread_count_) { - execution::execute( - threads_.executor(), + threads_.executor().execute( [this] { std::unique_lock<std::mutex> lock(mutex_); @@ -252,8 +251,8 @@ void fork_join_sort(Iterator begin, Iterator end) { fork_executor fork(pool); join_guard join(fork); - execution::execute(fork, [=]{ fork_join_sort(begin, begin + n / 2); }); - execution::execute(fork, [=]{ fork_join_sort(begin + n / 2, end); }); + fork.execute([=]{ fork_join_sort(begin, begin + n / 2); }); + fork.execute([=]{ fork_join_sort(begin + n / 2, end); }); } std::inplace_merge(begin, begin + n / 2, end); } diff --git a/3rdparty/asio/src/examples/cpp11/files/async_file_copy.cpp b/3rdparty/asio/src/examples/cpp11/files/async_file_copy.cpp new file mode 100644 index 00000000000..edfb2765ed5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/files/async_file_copy.cpp @@ -0,0 +1,101 @@ +// +// async_file_copy.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include "asio.hpp" + +#if defined(ASIO_HAS_FILE) + +class file_copier +{ +public: + file_copier(asio::io_context& io_context, + const char* from, const char* to) + : from_file_(io_context, from, + asio::stream_file::read_only), + to_file_(io_context, to, + asio::stream_file::write_only + | asio::stream_file::create + | asio::stream_file::truncate) + { + } + + void start() + { + do_read(); + } + +private: + void do_read() + { + from_file_.async_read_some(asio::buffer(data_), + [this](std::error_code error, std::size_t n) + { + if (!error) + { + do_write(n); + } + else if (error != asio::error::eof) + { + std::cerr << "Error copying file: " << error.message() << "\n"; + } + }); + } + + void do_write(std::size_t n) + { + asio::async_write(to_file_, asio::buffer(data_, n), + [this](std::error_code error, std::size_t /*n*/) + { + if (!error) + { + do_read(); + } + else + { + std::cerr << "Error copying file: " << error.message() << "\n"; + } + }); + } + + asio::stream_file from_file_; + asio::stream_file to_file_; + char data_[4096]; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cerr << "Usage: async_file_copy <from> <to>\n"; + return 1; + } + + asio::io_context io_context; + + file_copier copier(io_context, argv[1], argv[2]); + copier.start(); + + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + return 1; + } + + return 0; +} + +#else // defined(ASIO_HAS_FILE) +int main() {} +#endif // defined(ASIO_HAS_FILE) diff --git a/3rdparty/asio/src/examples/cpp11/files/blocking_file_copy.cpp b/3rdparty/asio/src/examples/cpp11/files/blocking_file_copy.cpp new file mode 100644 index 00000000000..6e111b4909d --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/files/blocking_file_copy.cpp @@ -0,0 +1,65 @@ +// +// blocking_file_copy.cpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include "asio.hpp" + +#if defined(ASIO_HAS_FILE) + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cerr << "Usage: blocking_file_copy <from> <to>\n"; + return 1; + } + + asio::io_context io_context; + + asio::stream_file from_file(io_context, argv[1], + asio::stream_file::read_only); + + asio::stream_file to_file(io_context, argv[2], + asio::stream_file::write_only + | asio::stream_file::create + | asio::stream_file::truncate); + + char data[4096]; + std::error_code error; + for (;;) + { + std::size_t n = from_file.read_some(asio::buffer(data), error); + if (error) + break; + asio::write(to_file, asio::buffer(data, n), error); + if (error) + break; + } + + if (error && error != asio::error::eof) + { + std::cerr << "Error copying file: " << error.message() << "\n"; + return 1; + } + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + return 1; + } + + return 0; +} + +#else // defined(ASIO_HAS_FILE) +int main() {} +#endif // defined(ASIO_HAS_FILE) diff --git a/3rdparty/asio/src/examples/cpp11/fork/daemon.cpp b/3rdparty/asio/src/examples/cpp11/fork/daemon.cpp index c63d5c1392f..547acb33a5a 100644 --- a/3rdparty/asio/src/examples/cpp11/fork/daemon.cpp +++ b/3rdparty/asio/src/examples/cpp11/fork/daemon.cpp @@ -2,7 +2,7 @@ // daemon.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/fork/process_per_connection.cpp b/3rdparty/asio/src/examples/cpp11/fork/process_per_connection.cpp index 217d5d945ae..cad52e7ab9f 100644 --- a/3rdparty/asio/src/examples/cpp11/fork/process_per_connection.cpp +++ b/3rdparty/asio/src/examples/cpp11/fork/process_per_connection.cpp @@ -2,7 +2,7 @@ // process_per_connection.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/futures/daytime_client.cpp b/3rdparty/asio/src/examples/cpp11/futures/daytime_client.cpp index 7744d630cb9..2f5314ede39 100644 --- a/3rdparty/asio/src/examples/cpp11/futures/daytime_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/futures/daytime_client.cpp @@ -2,7 +2,7 @@ // daytime_client.cpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -77,8 +77,7 @@ int main(int argc, char* argv[]) // We run the io_context off in its own thread so that it operates // completely asynchronously with respect to the rest of the program. asio::io_context io_context; - auto work = asio::require(io_context.get_executor(), - asio::execution::outstanding_work.tracked); + auto work = asio::make_work_guard(io_context); std::thread thread([&io_context](){ io_context.run(); }); get_daytime(io_context, argv[1]); diff --git a/3rdparty/asio/src/examples/cpp11/handler_tracking/async_tcp_echo_server.cpp b/3rdparty/asio/src/examples/cpp11/handler_tracking/async_tcp_echo_server.cpp index b18e4b2f19e..42a31f7b316 100644 --- a/3rdparty/asio/src/examples/cpp11/handler_tracking/async_tcp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/handler_tracking/async_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // async_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp b/3rdparty/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp index 464663b60d2..57b162a51e8 100644 --- a/3rdparty/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp +++ b/3rdparty/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp @@ -2,7 +2,7 @@ // custom_tracking.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -187,7 +187,7 @@ struct custom_tracking // Record a reactor-based operation that is associated with a handler. static void reactor_operation(const tracked_handler& h, - const char* op_name, const asio::error_code& ec) + const char* op_name, const std::error_code& ec) { std::printf( "Performed operation %s.%s for native_handle = %" PRIuMAX @@ -197,7 +197,7 @@ struct custom_tracking // Record a reactor-based operation that is associated with a handler. static void reactor_operation(const tracked_handler& h, - const char* op_name, const asio::error_code& ec, + const char* op_name, const std::error_code& ec, std::size_t bytes_transferred) { std::printf( diff --git a/3rdparty/asio/src/examples/cpp11/http/client/async_client.cpp b/3rdparty/asio/src/examples/cpp11/http/client/async_client.cpp new file mode 100644 index 00000000000..309ae252147 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/client/async_client.cpp @@ -0,0 +1,204 @@ +// +// async_client.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <functional> +#include <iostream> +#include <istream> +#include <ostream> +#include <string> +#include <asio.hpp> + +using asio::ip::tcp; + +class client +{ +public: + client(asio::io_context& io_context, + const std::string& server, const std::string& path) + : resolver_(io_context), + socket_(io_context) + { + // Form the request. We specify the "Connection: close" header so that the + // server will close the socket after transmitting the response. This will + // allow us to treat all data up until the EOF as the content. + std::ostream request_stream(&request_); + request_stream << "GET " << path << " HTTP/1.0\r\n"; + request_stream << "Host: " << server << "\r\n"; + request_stream << "Accept: */*\r\n"; + request_stream << "Connection: close\r\n\r\n"; + + // Start an asynchronous resolve to translate the server and service names + // into a list of endpoints. + resolver_.async_resolve(server, "http", + std::bind(&client::handle_resolve, this, + asio::placeholders::error, + asio::placeholders::results)); + } + +private: + void handle_resolve(const std::error_code& err, + const tcp::resolver::results_type& endpoints) + { + if (!err) + { + // Attempt a connection to each endpoint in the list until we + // successfully establish a connection. + asio::async_connect(socket_, endpoints, + std::bind(&client::handle_connect, this, + asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err.message() << "\n"; + } + } + + void handle_connect(const std::error_code& err) + { + if (!err) + { + // The connection was successful. Send the request. + asio::async_write(socket_, request_, + std::bind(&client::handle_write_request, this, + asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err.message() << "\n"; + } + } + + void handle_write_request(const std::error_code& err) + { + if (!err) + { + // Read the response status line. The response_ streambuf will + // automatically grow to accommodate the entire line. The growth may be + // limited by passing a maximum size to the streambuf constructor. + asio::async_read_until(socket_, response_, "\r\n", + std::bind(&client::handle_read_status_line, this, + asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err.message() << "\n"; + } + } + + void handle_read_status_line(const std::error_code& err) + { + if (!err) + { + // Check that response is OK. + std::istream response_stream(&response_); + std::string http_version; + response_stream >> http_version; + unsigned int status_code; + response_stream >> status_code; + std::string status_message; + std::getline(response_stream, status_message); + if (!response_stream || http_version.substr(0, 5) != "HTTP/") + { + std::cout << "Invalid response\n"; + return; + } + if (status_code != 200) + { + std::cout << "Response returned with status code "; + std::cout << status_code << "\n"; + return; + } + + // Read the response headers, which are terminated by a blank line. + asio::async_read_until(socket_, response_, "\r\n\r\n", + std::bind(&client::handle_read_headers, this, + asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err << "\n"; + } + } + + void handle_read_headers(const std::error_code& err) + { + if (!err) + { + // Process the response headers. + std::istream response_stream(&response_); + std::string header; + while (std::getline(response_stream, header) && header != "\r") + std::cout << header << "\n"; + std::cout << "\n"; + + // Write whatever content we already have to output. + if (response_.size() > 0) + std::cout << &response_; + + // Start reading remaining data until EOF. + asio::async_read(socket_, response_, + asio::transfer_at_least(1), + std::bind(&client::handle_read_content, this, + asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err << "\n"; + } + } + + void handle_read_content(const std::error_code& err) + { + if (!err) + { + // Write all of the data that has been read so far. + std::cout << &response_; + + // Continue reading remaining data until EOF. + asio::async_read(socket_, response_, + asio::transfer_at_least(1), + std::bind(&client::handle_read_content, this, + asio::placeholders::error)); + } + else if (err != asio::error::eof) + { + std::cout << "Error: " << err << "\n"; + } + } + + tcp::resolver resolver_; + tcp::socket socket_; + asio::streambuf request_; + asio::streambuf response_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cout << "Usage: async_client <server> <path>\n"; + std::cout << "Example:\n"; + std::cout << " async_client www.boost.org /LICENSE_1_0.txt\n"; + return 1; + } + + asio::io_context io_context; + client c(io_context, argv[1], argv[2]); + io_context.run(); + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/http/client/sync_client.cpp b/3rdparty/asio/src/examples/cpp11/http/client/sync_client.cpp new file mode 100644 index 00000000000..4f5ad099317 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/client/sync_client.cpp @@ -0,0 +1,106 @@ +// +// sync_client.cpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include <istream> +#include <ostream> +#include <string> +#include <asio.hpp> + +using asio::ip::tcp; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cout << "Usage: sync_client <server> <path>\n"; + std::cout << "Example:\n"; + std::cout << " sync_client www.boost.org /LICENSE_1_0.txt\n"; + return 1; + } + + asio::io_context io_context; + + // Get a list of endpoints corresponding to the server name. + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = resolver.resolve(argv[1], "http"); + + // Try each endpoint until we successfully establish a connection. + tcp::socket socket(io_context); + asio::connect(socket, endpoints); + + // Form the request. We specify the "Connection: close" header so that the + // server will close the socket after transmitting the response. This will + // allow us to treat all data up until the EOF as the content. + asio::streambuf request; + std::ostream request_stream(&request); + request_stream << "GET " << argv[2] << " HTTP/1.0\r\n"; + request_stream << "Host: " << argv[1] << "\r\n"; + request_stream << "Accept: */*\r\n"; + request_stream << "Connection: close\r\n\r\n"; + + // Send the request. + asio::write(socket, request); + + // Read the response status line. The response streambuf will automatically + // grow to accommodate the entire line. The growth may be limited by passing + // a maximum size to the streambuf constructor. + asio::streambuf response; + asio::read_until(socket, response, "\r\n"); + + // Check that response is OK. + std::istream response_stream(&response); + std::string http_version; + response_stream >> http_version; + unsigned int status_code; + response_stream >> status_code; + std::string status_message; + std::getline(response_stream, status_message); + if (!response_stream || http_version.substr(0, 5) != "HTTP/") + { + std::cout << "Invalid response\n"; + return 1; + } + if (status_code != 200) + { + std::cout << "Response returned with status code " << status_code << "\n"; + return 1; + } + + // Read the response headers, which are terminated by a blank line. + asio::read_until(socket, response, "\r\n\r\n"); + + // Process the response headers. + std::string header; + while (std::getline(response_stream, header) && header != "\r") + std::cout << header << "\n"; + std::cout << "\n"; + + // Write whatever content we already have to output. + if (response.size() > 0) + std::cout << &response; + + // Read until EOF, writing data to output as we go. + std::error_code error; + while (asio::read(socket, response, + asio::transfer_at_least(1), error)) + std::cout << &response; + if (error != asio::error::eof) + throw std::system_error(error); + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/http/server/connection.cpp b/3rdparty/asio/src/examples/cpp11/http/server/connection.cpp index 704ae6d1147..58d619fec76 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/connection.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/connection.cpp @@ -2,7 +2,7 @@ // connection.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -10,7 +10,6 @@ #include "connection.hpp" #include <utility> -#include <vector> #include "connection_manager.hpp" #include "request_handler.hpp" @@ -78,7 +77,7 @@ void connection::do_write() if (!ec) { // Initiate graceful connection closure. - asio::error_code ignored_ec; + std::error_code ignored_ec; socket_.shutdown(asio::ip::tcp::socket::shutdown_both, ignored_ec); } diff --git a/3rdparty/asio/src/examples/cpp11/http/server/connection.hpp b/3rdparty/asio/src/examples/cpp11/http/server/connection.hpp index b7bf762820a..1d671ebdcbe 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/connection.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/connection.hpp @@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -11,9 +11,9 @@ #ifndef HTTP_CONNECTION_HPP #define HTTP_CONNECTION_HPP +#include <asio.hpp> #include <array> #include <memory> -#include <asio.hpp> #include "reply.hpp" #include "request.hpp" #include "request_handler.hpp" diff --git a/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.cpp b/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.cpp index 43221162f20..88161919330 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.cpp @@ -2,7 +2,7 @@ // connection_manager.cpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.hpp b/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.hpp index af57cc9ce54..0b35408fae5 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/connection_manager.hpp @@ -2,7 +2,7 @@ // connection_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/header.hpp b/3rdparty/asio/src/examples/cpp11/http/server/header.hpp index bccbf977a9e..e91e6ff23a2 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/header.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/header.hpp @@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/main.cpp b/3rdparty/asio/src/examples/cpp11/http/server/main.cpp index e23a5607791..b76044a96cd 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/main.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/main.cpp @@ -2,7 +2,7 @@ // main.cpp // ~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/mime_types.cpp b/3rdparty/asio/src/examples/cpp11/http/server/mime_types.cpp index a59955e8d5b..23153caa1df 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/mime_types.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/mime_types.cpp @@ -2,7 +2,7 @@ // mime_types.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/mime_types.hpp b/3rdparty/asio/src/examples/cpp11/http/server/mime_types.hpp index aef5676104e..fcefce5437b 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/mime_types.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/mime_types.hpp @@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/reply.cpp b/3rdparty/asio/src/examples/cpp11/http/server/reply.cpp index 301ff3a1ab9..9d8f04e2ae1 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/reply.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/reply.cpp @@ -2,7 +2,7 @@ // reply.cpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/reply.hpp b/3rdparty/asio/src/examples/cpp11/http/server/reply.hpp index c8f3f11040d..f1eee1f891b 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/reply.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/reply.hpp @@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/request.hpp b/3rdparty/asio/src/examples/cpp11/http/server/request.hpp index 8a6a2bdf824..93a96db12b4 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/request.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/request.hpp @@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/request_handler.cpp b/3rdparty/asio/src/examples/cpp11/http/server/request_handler.cpp index 621a1ab22ec..97b4ac6a8e6 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/request_handler.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/request_handler.cpp @@ -2,7 +2,7 @@ // request_handler.cpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/request_handler.hpp b/3rdparty/asio/src/examples/cpp11/http/server/request_handler.hpp index dc3432d34a0..978b37ca537 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/request_handler.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/request_handler.hpp @@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/request_parser.cpp b/3rdparty/asio/src/examples/cpp11/http/server/request_parser.cpp index 3ab194a3ace..ff56e9c618a 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/request_parser.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/request_parser.cpp @@ -2,7 +2,7 @@ // request_parser.cpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/request_parser.hpp b/3rdparty/asio/src/examples/cpp11/http/server/request_parser.hpp index 68ac14e590f..260e8759acb 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/request_parser.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/request_parser.hpp @@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/server.cpp b/3rdparty/asio/src/examples/cpp11/http/server/server.cpp index d2c179ee08a..d824ebbf229 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/server.cpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server/server.hpp b/3rdparty/asio/src/examples/cpp11/http/server/server.hpp index 917fbdd3d06..c88d0149114 100644 --- a/3rdparty/asio/src/examples/cpp11/http/server/server.hpp +++ b/3rdparty/asio/src/examples/cpp11/http/server/server.hpp @@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/connection.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/connection.cpp new file mode 100644 index 00000000000..ab8ab9e0524 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/connection.cpp @@ -0,0 +1,89 @@ +// +// connection.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "connection.hpp" +#include <utility> +#include "request_handler.hpp" + +namespace http { +namespace server2 { + +connection::connection(asio::ip::tcp::socket socket, + request_handler& handler) + : socket_(std::move(socket)), + request_handler_(handler) +{ +} + +void connection::start() +{ + do_read(); +} + +void connection::do_read() +{ + auto self(shared_from_this()); + socket_.async_read_some(asio::buffer(buffer_), + [this, self](std::error_code ec, std::size_t bytes_transferred) + { + if (!ec) + { + request_parser::result_type result; + std::tie(result, std::ignore) = request_parser_.parse( + request_, buffer_.data(), buffer_.data() + bytes_transferred); + + if (result == request_parser::good) + { + request_handler_.handle_request(request_, reply_); + do_write(); + } + else if (result == request_parser::bad) + { + reply_ = reply::stock_reply(reply::bad_request); + do_write(); + } + else + { + do_read(); + } + } + + // If an error occurs then no new asynchronous operations are + // started. This means that all shared_ptr references to the + // connection object will disappear and the object will be + // destroyed automatically after this handler returns. The + // connection class's destructor closes the socket. + }); +} + +void connection::do_write() +{ + auto self(shared_from_this()); + asio::async_write(socket_, reply_.to_buffers(), + [this, self](std::error_code ec, std::size_t) + { + if (!ec) + { + // Initiate graceful connection closure. + std::error_code ignored_ec; + socket_.shutdown(asio::ip::tcp::socket::shutdown_both, + ignored_ec); + } + + // No new asynchronous operations are started. This means that + // all shared_ptr references to the connection object will + // disappear and the object will be destroyed automatically after + // this handler returns. The connection class's destructor closes + // the socket. + }); +} + +} // namespace server2 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/connection.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/connection.hpp new file mode 100644 index 00000000000..7d4a4735754 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/connection.hpp @@ -0,0 +1,71 @@ +// +// connection.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_CONNECTION_HPP +#define HTTP_SERVER2_CONNECTION_HPP + +#include <asio.hpp> +#include <array> +#include <memory> +#include "reply.hpp" +#include "request.hpp" +#include "request_handler.hpp" +#include "request_parser.hpp" + +namespace http { +namespace server2 { + +/// Represents a single connection from a client. +class connection + : public std::enable_shared_from_this<connection> +{ +public: + connection(const connection&) = delete; + connection& operator=(const connection&) = delete; + + /// Construct a connection with the given socket. + explicit connection(asio::ip::tcp::socket socket, + request_handler& handler); + + /// Start the first asynchronous operation for the connection. + void start(); + +private: + /// Perform an asynchronous read operation. + void do_read(); + + /// Perform an asynchronous write operation. + void do_write(); + + /// Socket for the connection. + asio::ip::tcp::socket socket_; + + /// The handler used to process the incoming request. + request_handler& request_handler_; + + /// Buffer for incoming data. + std::array<char, 8192> buffer_; + + /// The incoming request. + request request_; + + /// The parser for the incoming request. + request_parser request_parser_; + + /// The reply to be sent back to the client. + reply reply_; +}; + +typedef std::shared_ptr<connection> connection_ptr; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_CONNECTION_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/header.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/header.hpp new file mode 100644 index 00000000000..f888dde03c0 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/header.hpp @@ -0,0 +1,28 @@ +// +// header.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_HEADER_HPP +#define HTTP_SERVER2_HEADER_HPP + +#include <string> + +namespace http { +namespace server2 { + +struct header +{ + std::string name; + std::string value; +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_HEADER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/io_context_pool.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/io_context_pool.cpp new file mode 100644 index 00000000000..bea08903087 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/io_context_pool.cpp @@ -0,0 +1,64 @@ +// +// io_context_pool.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "server.hpp" +#include <stdexcept> +#include <thread> + +namespace http { +namespace server2 { + +io_context_pool::io_context_pool(std::size_t pool_size) + : next_io_context_(0) +{ + if (pool_size == 0) + throw std::runtime_error("io_context_pool size is 0"); + + // Give all the io_contexts work to do so that their run() functions will not + // exit until they are explicitly stopped. + for (std::size_t i = 0; i < pool_size; ++i) + { + io_context_ptr io_context(new asio::io_context); + io_contexts_.push_back(io_context); + work_.push_back(asio::make_work_guard(*io_context)); + } +} + +void io_context_pool::run() +{ + // Create a pool of threads to run all of the io_contexts. + std::vector<std::thread> threads; + for (std::size_t i = 0; i < io_contexts_.size(); ++i) + threads.emplace_back([this, i]{ io_contexts_[i]->run(); }); + + // Wait for all threads in the pool to exit. + for (std::size_t i = 0; i < threads.size(); ++i) + threads[i].join(); +} + +void io_context_pool::stop() +{ + // Explicitly stop all io_contexts. + for (std::size_t i = 0; i < io_contexts_.size(); ++i) + io_contexts_[i]->stop(); +} + +asio::io_context& io_context_pool::get_io_context() +{ + // Use a round-robin scheme to choose the next io_context to use. + asio::io_context& io_context = *io_contexts_[next_io_context_]; + ++next_io_context_; + if (next_io_context_ == io_contexts_.size()) + next_io_context_ = 0; + return io_context; +} + +} // namespace server2 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/io_context_pool.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/io_context_pool.hpp new file mode 100644 index 00000000000..0946ba6e484 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/io_context_pool.hpp @@ -0,0 +1,59 @@ +// +// io_context_pool.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_IO_SERVICE_POOL_HPP +#define HTTP_SERVER2_IO_SERVICE_POOL_HPP + +#include <asio.hpp> +#include <list> +#include <memory> +#include <vector> + +namespace http { +namespace server2 { + +/// A pool of io_context objects. +class io_context_pool +{ +public: + /// Construct the io_context pool. + explicit io_context_pool(std::size_t pool_size); + + /// Run all io_context objects in the pool. + void run(); + + /// Stop all io_context objects in the pool. + void stop(); + + /// Get an io_context to use. + asio::io_context& get_io_context(); + +private: + io_context_pool(const io_context_pool&) = delete; + io_context_pool& operator=(const io_context_pool&) = delete; + + typedef std::shared_ptr<asio::io_context> io_context_ptr; + typedef asio::executor_work_guard< + asio::io_context::executor_type> io_context_work; + + /// The pool of io_contexts. + std::vector<io_context_ptr> io_contexts_; + + /// The work that keeps the io_contexts running. + std::list<io_context_work> work_; + + /// The next io_context to use for a connection. + std::size_t next_io_context_; +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_IO_SERVICE_POOL_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/main.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/main.cpp new file mode 100644 index 00000000000..5b6a9a36cb3 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/main.cpp @@ -0,0 +1,44 @@ +// +// main.cpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include <string> +#include <asio.hpp> +#include "server.hpp" + +int main(int argc, char* argv[]) +{ + try + { + // Check command line arguments. + if (argc != 5) + { + std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n"; + std::cerr << " For IPv4, try:\n"; + std::cerr << " receiver 0.0.0.0 80 1 .\n"; + std::cerr << " For IPv6, try:\n"; + std::cerr << " receiver 0::0 80 1 .\n"; + return 1; + } + + // Initialise the server. + std::size_t num_threads = std::stoi(argv[3]); + http::server2::server s(argv[1], argv[2], argv[4], num_threads); + + // Run the server until stopped. + s.run(); + } + catch (std::exception& e) + { + std::cerr << "exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/mime_types.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/mime_types.cpp new file mode 100644 index 00000000000..03079331e93 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/mime_types.cpp @@ -0,0 +1,46 @@ +// +// mime_types.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "mime_types.hpp" + +namespace http { +namespace server2 { +namespace mime_types { + +struct mapping +{ + const char* extension; + const char* mime_type; +} mappings[] = +{ + { "gif", "image/gif" }, + { "htm", "text/html" }, + { "html", "text/html" }, + { "jpg", "image/jpeg" }, + { "png", "image/png" }, + { 0, 0 } // Marks end of list. +}; + +std::string extension_to_type(const std::string& extension) +{ + for (mapping* m = mappings; m->extension; ++m) + { + if (m->extension == extension) + { + return m->mime_type; + } + } + + return "text/plain"; +} + +} // namespace mime_types +} // namespace server2 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/mime_types.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/mime_types.hpp new file mode 100644 index 00000000000..32985c18e59 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/mime_types.hpp @@ -0,0 +1,27 @@ +// +// mime_types.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_MIME_TYPES_HPP +#define HTTP_SERVER2_MIME_TYPES_HPP + +#include <string> + +namespace http { +namespace server2 { +namespace mime_types { + +/// Convert a file extension into a MIME type. +std::string extension_to_type(const std::string& extension); + +} // namespace mime_types +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_MIME_TYPES_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/reply.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/reply.cpp new file mode 100644 index 00000000000..d48bfd9e463 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/reply.cpp @@ -0,0 +1,255 @@ +// +// reply.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "reply.hpp" +#include <string> + +namespace http { +namespace server2 { + +namespace status_strings { + +const std::string ok = + "HTTP/1.0 200 OK\r\n"; +const std::string created = + "HTTP/1.0 201 Created\r\n"; +const std::string accepted = + "HTTP/1.0 202 Accepted\r\n"; +const std::string no_content = + "HTTP/1.0 204 No Content\r\n"; +const std::string multiple_choices = + "HTTP/1.0 300 Multiple Choices\r\n"; +const std::string moved_permanently = + "HTTP/1.0 301 Moved Permanently\r\n"; +const std::string moved_temporarily = + "HTTP/1.0 302 Moved Temporarily\r\n"; +const std::string not_modified = + "HTTP/1.0 304 Not Modified\r\n"; +const std::string bad_request = + "HTTP/1.0 400 Bad Request\r\n"; +const std::string unauthorized = + "HTTP/1.0 401 Unauthorized\r\n"; +const std::string forbidden = + "HTTP/1.0 403 Forbidden\r\n"; +const std::string not_found = + "HTTP/1.0 404 Not Found\r\n"; +const std::string internal_server_error = + "HTTP/1.0 500 Internal Server Error\r\n"; +const std::string not_implemented = + "HTTP/1.0 501 Not Implemented\r\n"; +const std::string bad_gateway = + "HTTP/1.0 502 Bad Gateway\r\n"; +const std::string service_unavailable = + "HTTP/1.0 503 Service Unavailable\r\n"; + +asio::const_buffer to_buffer(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return asio::buffer(ok); + case reply::created: + return asio::buffer(created); + case reply::accepted: + return asio::buffer(accepted); + case reply::no_content: + return asio::buffer(no_content); + case reply::multiple_choices: + return asio::buffer(multiple_choices); + case reply::moved_permanently: + return asio::buffer(moved_permanently); + case reply::moved_temporarily: + return asio::buffer(moved_temporarily); + case reply::not_modified: + return asio::buffer(not_modified); + case reply::bad_request: + return asio::buffer(bad_request); + case reply::unauthorized: + return asio::buffer(unauthorized); + case reply::forbidden: + return asio::buffer(forbidden); + case reply::not_found: + return asio::buffer(not_found); + case reply::internal_server_error: + return asio::buffer(internal_server_error); + case reply::not_implemented: + return asio::buffer(not_implemented); + case reply::bad_gateway: + return asio::buffer(bad_gateway); + case reply::service_unavailable: + return asio::buffer(service_unavailable); + default: + return asio::buffer(internal_server_error); + } +} + +} // namespace status_strings + +namespace misc_strings { + +const char name_value_separator[] = { ':', ' ' }; +const char crlf[] = { '\r', '\n' }; + +} // namespace misc_strings + +std::vector<asio::const_buffer> reply::to_buffers() +{ + std::vector<asio::const_buffer> buffers; + buffers.push_back(status_strings::to_buffer(status)); + for (std::size_t i = 0; i < headers.size(); ++i) + { + header& h = headers[i]; + buffers.push_back(asio::buffer(h.name)); + buffers.push_back(asio::buffer(misc_strings::name_value_separator)); + buffers.push_back(asio::buffer(h.value)); + buffers.push_back(asio::buffer(misc_strings::crlf)); + } + buffers.push_back(asio::buffer(misc_strings::crlf)); + buffers.push_back(asio::buffer(content)); + return buffers; +} + +namespace stock_replies { + +const char ok[] = ""; +const char created[] = + "<html>" + "<head><title>Created</title></head>" + "<body><h1>201 Created</h1></body>" + "</html>"; +const char accepted[] = + "<html>" + "<head><title>Accepted</title></head>" + "<body><h1>202 Accepted</h1></body>" + "</html>"; +const char no_content[] = + "<html>" + "<head><title>No Content</title></head>" + "<body><h1>204 Content</h1></body>" + "</html>"; +const char multiple_choices[] = + "<html>" + "<head><title>Multiple Choices</title></head>" + "<body><h1>300 Multiple Choices</h1></body>" + "</html>"; +const char moved_permanently[] = + "<html>" + "<head><title>Moved Permanently</title></head>" + "<body><h1>301 Moved Permanently</h1></body>" + "</html>"; +const char moved_temporarily[] = + "<html>" + "<head><title>Moved Temporarily</title></head>" + "<body><h1>302 Moved Temporarily</h1></body>" + "</html>"; +const char not_modified[] = + "<html>" + "<head><title>Not Modified</title></head>" + "<body><h1>304 Not Modified</h1></body>" + "</html>"; +const char bad_request[] = + "<html>" + "<head><title>Bad Request</title></head>" + "<body><h1>400 Bad Request</h1></body>" + "</html>"; +const char unauthorized[] = + "<html>" + "<head><title>Unauthorized</title></head>" + "<body><h1>401 Unauthorized</h1></body>" + "</html>"; +const char forbidden[] = + "<html>" + "<head><title>Forbidden</title></head>" + "<body><h1>403 Forbidden</h1></body>" + "</html>"; +const char not_found[] = + "<html>" + "<head><title>Not Found</title></head>" + "<body><h1>404 Not Found</h1></body>" + "</html>"; +const char internal_server_error[] = + "<html>" + "<head><title>Internal Server Error</title></head>" + "<body><h1>500 Internal Server Error</h1></body>" + "</html>"; +const char not_implemented[] = + "<html>" + "<head><title>Not Implemented</title></head>" + "<body><h1>501 Not Implemented</h1></body>" + "</html>"; +const char bad_gateway[] = + "<html>" + "<head><title>Bad Gateway</title></head>" + "<body><h1>502 Bad Gateway</h1></body>" + "</html>"; +const char service_unavailable[] = + "<html>" + "<head><title>Service Unavailable</title></head>" + "<body><h1>503 Service Unavailable</h1></body>" + "</html>"; + +std::string to_string(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return ok; + case reply::created: + return created; + case reply::accepted: + return accepted; + case reply::no_content: + return no_content; + case reply::multiple_choices: + return multiple_choices; + case reply::moved_permanently: + return moved_permanently; + case reply::moved_temporarily: + return moved_temporarily; + case reply::not_modified: + return not_modified; + case reply::bad_request: + return bad_request; + case reply::unauthorized: + return unauthorized; + case reply::forbidden: + return forbidden; + case reply::not_found: + return not_found; + case reply::internal_server_error: + return internal_server_error; + case reply::not_implemented: + return not_implemented; + case reply::bad_gateway: + return bad_gateway; + case reply::service_unavailable: + return service_unavailable; + default: + return internal_server_error; + } +} + +} // namespace stock_replies + +reply reply::stock_reply(reply::status_type status) +{ + reply rep; + rep.status = status; + rep.content = stock_replies::to_string(status); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "text/html"; + return rep; +} + +} // namespace server2 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/reply.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/reply.hpp new file mode 100644 index 00000000000..f4be7ca94fe --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/reply.hpp @@ -0,0 +1,64 @@ +// +// reply.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_REPLY_HPP +#define HTTP_SERVER2_REPLY_HPP + +#include <string> +#include <vector> +#include <asio.hpp> +#include "header.hpp" + +namespace http { +namespace server2 { + +/// A reply to be sent to a client. +struct reply +{ + /// The status of the reply. + enum status_type + { + ok = 200, + created = 201, + accepted = 202, + no_content = 204, + multiple_choices = 300, + moved_permanently = 301, + moved_temporarily = 302, + not_modified = 304, + bad_request = 400, + unauthorized = 401, + forbidden = 403, + not_found = 404, + internal_server_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503 + } status; + + /// The headers to be included in the reply. + std::vector<header> headers; + + /// The content to be sent in the reply. + std::string content; + + /// Convert the reply into a vector of buffers. The buffers do not own the + /// underlying memory blocks, therefore the reply object must remain valid and + /// not be changed until the write operation has completed. + std::vector<asio::const_buffer> to_buffers(); + + /// Get a stock reply. + static reply stock_reply(status_type status); +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_REPLY_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/request.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/request.hpp new file mode 100644 index 00000000000..b0000b00967 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/request.hpp @@ -0,0 +1,34 @@ +// +// request.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_REQUEST_HPP +#define HTTP_SERVER2_REQUEST_HPP + +#include <string> +#include <vector> +#include "header.hpp" + +namespace http { +namespace server2 { + +/// A request received from a client. +struct request +{ + std::string method; + std::string uri; + int http_version_major; + int http_version_minor; + std::vector<header> headers; +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_REQUEST_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/request_handler.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/request_handler.cpp new file mode 100644 index 00000000000..c57fa9757f5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/request_handler.cpp @@ -0,0 +1,121 @@ +// +// request_handler.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "request_handler.hpp" +#include <fstream> +#include <sstream> +#include <string> +#include "mime_types.hpp" +#include "reply.hpp" +#include "request.hpp" + +namespace http { +namespace server2 { + +request_handler::request_handler(const std::string& doc_root) + : doc_root_(doc_root) +{ +} + +void request_handler::handle_request(const request& req, reply& rep) +{ + // Decode url to path. + std::string request_path; + if (!url_decode(req.uri, request_path)) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // Request path must be absolute and not contain "..". + if (request_path.empty() || request_path[0] != '/' + || request_path.find("..") != std::string::npos) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // If path ends in slash (i.e. is a directory) then add "index.html". + if (request_path[request_path.size() - 1] == '/') + { + request_path += "index.html"; + } + + // Determine the file extension. + std::size_t last_slash_pos = request_path.find_last_of("/"); + std::size_t last_dot_pos = request_path.find_last_of("."); + std::string extension; + if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) + { + extension = request_path.substr(last_dot_pos + 1); + } + + // Open the file to send back. + std::string full_path = doc_root_ + request_path; + std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); + if (!is) + { + rep = reply::stock_reply(reply::not_found); + return; + } + + // Fill out the reply to be sent to the client. + rep.status = reply::ok; + char buf[512]; + while (is.read(buf, sizeof(buf)).gcount() > 0) + rep.content.append(buf, is.gcount()); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = mime_types::extension_to_type(extension); +} + +bool request_handler::url_decode(const std::string& in, std::string& out) +{ + out.clear(); + out.reserve(in.size()); + for (std::size_t i = 0; i < in.size(); ++i) + { + if (in[i] == '%') + { + if (i + 3 <= in.size()) + { + int value = 0; + std::istringstream is(in.substr(i + 1, 2)); + if (is >> std::hex >> value) + { + out += static_cast<char>(value); + i += 2; + } + else + { + return false; + } + } + else + { + return false; + } + } + else if (in[i] == '+') + { + out += ' '; + } + else + { + out += in[i]; + } + } + return true; +} + +} // namespace server2 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/request_handler.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/request_handler.hpp new file mode 100644 index 00000000000..c9e9ebf418f --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/request_handler.hpp @@ -0,0 +1,47 @@ +// +// request_handler.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_REQUEST_HANDLER_HPP +#define HTTP_SERVER2_REQUEST_HANDLER_HPP + +#include <string> + +namespace http { +namespace server2 { + +struct reply; +struct request; + +/// The common handler for all incoming requests. +class request_handler +{ +public: + request_handler(const request_handler&) = delete; + request_handler& operator=(const request_handler&) = delete; + + /// Construct with a directory containing files to be served. + explicit request_handler(const std::string& doc_root); + + /// Handle a request and produce a reply. + void handle_request(const request& req, reply& rep); + +private: + /// The directory containing the files to be served. + std::string doc_root_; + + /// Perform URL-decoding on a string. Returns false if the encoding was + /// invalid. + static bool url_decode(const std::string& in, std::string& out); +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_REQUEST_HANDLER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/request_parser.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/request_parser.cpp new file mode 100644 index 00000000000..2cd8ac00b47 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/request_parser.cpp @@ -0,0 +1,315 @@ +// +// request_parser.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "request_parser.hpp" +#include "request.hpp" + +namespace http { +namespace server2 { + +request_parser::request_parser() + : state_(method_start) +{ +} + +void request_parser::reset() +{ + state_ = method_start; +} + +request_parser::result_type request_parser::consume(request& req, char input) +{ + switch (state_) + { + case method_start: + if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + state_ = method; + req.method.push_back(input); + return indeterminate; + } + case method: + if (input == ' ') + { + state_ = uri; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.method.push_back(input); + return indeterminate; + } + case uri: + if (input == ' ') + { + state_ = http_version_h; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.uri.push_back(input); + return indeterminate; + } + case http_version_h: + if (input == 'H') + { + state_ = http_version_t_1; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_1: + if (input == 'T') + { + state_ = http_version_t_2; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_2: + if (input == 'T') + { + state_ = http_version_p; + return indeterminate; + } + else + { + return bad; + } + case http_version_p: + if (input == 'P') + { + state_ = http_version_slash; + return indeterminate; + } + else + { + return bad; + } + case http_version_slash: + if (input == '/') + { + req.http_version_major = 0; + req.http_version_minor = 0; + state_ = http_version_major_start; + return indeterminate; + } + else + { + return bad; + } + case http_version_major_start: + if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + state_ = http_version_major; + return indeterminate; + } + else + { + return bad; + } + case http_version_major: + if (input == '.') + { + state_ = http_version_minor_start; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor_start: + if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + state_ = http_version_minor; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor: + if (input == '\r') + { + state_ = expecting_newline_1; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_1: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case header_line_start: + if (input == '\r') + { + state_ = expecting_newline_3; + return indeterminate; + } + else if (!req.headers.empty() && (input == ' ' || input == '\t')) + { + state_ = header_lws; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.push_back(header()); + req.headers.back().name.push_back(input); + state_ = header_name; + return indeterminate; + } + case header_lws: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (input == ' ' || input == '\t') + { + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + state_ = header_value; + req.headers.back().value.push_back(input); + return indeterminate; + } + case header_name: + if (input == ':') + { + state_ = space_before_header_value; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.back().name.push_back(input); + return indeterminate; + } + case space_before_header_value: + if (input == ' ') + { + state_ = header_value; + return indeterminate; + } + else + { + return bad; + } + case header_value: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.headers.back().value.push_back(input); + return indeterminate; + } + case expecting_newline_2: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_3: + return (input == '\n') ? good : bad; + default: + return bad; + } +} + +bool request_parser::is_char(int c) +{ + return c >= 0 && c <= 127; +} + +bool request_parser::is_ctl(int c) +{ + return (c >= 0 && c <= 31) || (c == 127); +} + +bool request_parser::is_tspecial(int c) +{ + switch (c) + { + case '(': case ')': case '<': case '>': case '@': + case ',': case ';': case ':': case '\\': case '"': + case '/': case '[': case ']': case '?': case '=': + case '{': case '}': case ' ': case '\t': + return true; + default: + return false; + } +} + +bool request_parser::is_digit(int c) +{ + return c >= '0' && c <= '9'; +} + +} // namespace server2 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/request_parser.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/request_parser.hpp new file mode 100644 index 00000000000..1d11168b72d --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/request_parser.hpp @@ -0,0 +1,96 @@ +// +// request_parser.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_REQUEST_PARSER_HPP +#define HTTP_SERVER2_REQUEST_PARSER_HPP + +#include <tuple> + +namespace http { +namespace server2 { + +struct request; + +/// Parser for incoming requests. +class request_parser +{ +public: + /// Construct ready to parse the request method. + request_parser(); + + /// Reset to initial parser state. + void reset(); + + /// Result of parse. + enum result_type { good, bad, indeterminate }; + + /// Parse some data. The enum return value is good when a complete request has + /// been parsed, bad if the data is invalid, indeterminate when more data is + /// required. The InputIterator return value indicates how much of the input + /// has been consumed. + template <typename InputIterator> + std::tuple<result_type, InputIterator> parse(request& req, + InputIterator begin, InputIterator end) + { + while (begin != end) + { + result_type result = consume(req, *begin++); + if (result == good || result == bad) + return std::make_tuple(result, begin); + } + return std::make_tuple(indeterminate, begin); + } + +private: + /// Handle the next character of input. + result_type consume(request& req, char input); + + /// Check if a byte is an HTTP character. + static bool is_char(int c); + + /// Check if a byte is an HTTP control character. + static bool is_ctl(int c); + + /// Check if a byte is defined as an HTTP tspecial character. + static bool is_tspecial(int c); + + /// Check if a byte is a digit. + static bool is_digit(int c); + + /// The current state of the parser. + enum state + { + method_start, + method, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + expecting_newline_2, + expecting_newline_3 + } state_; +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_REQUEST_PARSER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/server.cpp b/3rdparty/asio/src/examples/cpp11/http/server2/server.cpp new file mode 100644 index 00000000000..2ae733086a5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/server.cpp @@ -0,0 +1,86 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "server.hpp" +#include <signal.h> +#include <utility> +#include "connection.hpp" + +namespace http { +namespace server2 { + +server::server(const std::string& address, const std::string& port, + const std::string& doc_root, std::size_t io_context_pool_size) + : io_context_pool_(io_context_pool_size), + signals_(io_context_pool_.get_io_context()), + acceptor_(io_context_pool_.get_io_context()), + request_handler_(doc_root) +{ + // Register to handle the signals that indicate when the server should exit. + // It is safe to register for the same signal multiple times in a program, + // provided all registration for the specified signal is made through Asio. + signals_.add(SIGINT); + signals_.add(SIGTERM); +#if defined(SIGQUIT) + signals_.add(SIGQUIT); +#endif // defined(SIGQUIT) + + do_await_stop(); + + // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). + asio::ip::tcp::resolver resolver(acceptor_.get_executor()); + asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); + acceptor_.open(endpoint.protocol()); + acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true)); + acceptor_.bind(endpoint); + acceptor_.listen(); + + do_accept(); +} + +void server::run() +{ + io_context_pool_.run(); +} + +void server::do_accept() +{ + acceptor_.async_accept(io_context_pool_.get_io_context(), + [this](std::error_code ec, asio::ip::tcp::socket socket) + { + // Check whether the server was stopped by a signal before this + // completion handler had a chance to run. + if (!acceptor_.is_open()) + { + return; + } + + if (!ec) + { + std::make_shared<connection>( + std::move(socket), request_handler_)->start(); + } + + do_accept(); + }); +} + +void server::do_await_stop() +{ + signals_.async_wait( + [this](std::error_code /*ec*/, int /*signo*/) + { + io_context_pool_.stop(); + }); +} + +} // namespace server2 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server2/server.hpp b/3rdparty/asio/src/examples/cpp11/http/server2/server.hpp new file mode 100644 index 00000000000..9d34a77ed7c --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server2/server.hpp @@ -0,0 +1,60 @@ +// +// server.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER2_SERVER_HPP +#define HTTP_SERVER2_SERVER_HPP + +#include <asio.hpp> +#include <string> +#include "io_context_pool.hpp" +#include "request_handler.hpp" + +namespace http { +namespace server2 { + +/// The top-level class of the HTTP server. +class server +{ +public: + server(const server&) = delete; + server& operator=(const server&) = delete; + + /// Construct the server to listen on the specified TCP address and port, and + /// serve up files from the given directory. + explicit server(const std::string& address, const std::string& port, + const std::string& doc_root, std::size_t io_context_pool_size); + + /// Run the server's io_context loop. + void run(); + +private: + /// Perform an asynchronous accept operation. + void do_accept(); + + /// Wait for a request to stop the server. + void do_await_stop(); + + /// The pool of io_context objects used to perform asynchronous operations. + io_context_pool io_context_pool_; + + /// The signal_set is used to register for process termination notifications. + asio::signal_set signals_; + + /// Acceptor used to listen for incoming connections. + asio::ip::tcp::acceptor acceptor_; + + /// The handler for all incoming requests. + request_handler request_handler_; +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_SERVER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/connection.cpp b/3rdparty/asio/src/examples/cpp11/http/server3/connection.cpp new file mode 100644 index 00000000000..d4070364fb4 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/connection.cpp @@ -0,0 +1,89 @@ +// +// connection.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "connection.hpp" +#include <utility> +#include "request_handler.hpp" + +namespace http { +namespace server3 { + +connection::connection(asio::ip::tcp::socket socket, + request_handler& handler) + : socket_(std::move(socket)), + request_handler_(handler) +{ +} + +void connection::start() +{ + do_read(); +} + +void connection::do_read() +{ + auto self(shared_from_this()); + socket_.async_read_some(asio::buffer(buffer_), + [this, self](std::error_code ec, std::size_t bytes_transferred) + { + if (!ec) + { + request_parser::result_type result; + std::tie(result, std::ignore) = request_parser_.parse( + request_, buffer_.data(), buffer_.data() + bytes_transferred); + + if (result == request_parser::good) + { + request_handler_.handle_request(request_, reply_); + do_write(); + } + else if (result == request_parser::bad) + { + reply_ = reply::stock_reply(reply::bad_request); + do_write(); + } + else + { + do_read(); + } + } + + // If an error occurs then no new asynchronous operations are + // started. This means that all shared_ptr references to the + // connection object will disappear and the object will be + // destroyed automatically after this handler returns. The + // connection class's destructor closes the socket. + }); +} + +void connection::do_write() +{ + auto self(shared_from_this()); + asio::async_write(socket_, reply_.to_buffers(), + [this, self](std::error_code ec, std::size_t) + { + if (!ec) + { + // Initiate graceful connection closure. + std::error_code ignored_ec; + socket_.shutdown(asio::ip::tcp::socket::shutdown_both, + ignored_ec); + } + + // No new asynchronous operations are started. This means that + // all shared_ptr references to the connection object will + // disappear and the object will be destroyed automatically after + // this handler returns. The connection class's destructor closes + // the socket. + }); +} + +} // namespace server3 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/connection.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/connection.hpp new file mode 100644 index 00000000000..878cd45d366 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/connection.hpp @@ -0,0 +1,71 @@ +// +// connection.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_CONNECTION_HPP +#define HTTP_SERVER3_CONNECTION_HPP + +#include <asio.hpp> +#include <array> +#include <memory> +#include "reply.hpp" +#include "request.hpp" +#include "request_handler.hpp" +#include "request_parser.hpp" + +namespace http { +namespace server3 { + +/// Represents a single connection from a client. +class connection + : public std::enable_shared_from_this<connection> +{ +public: + connection(const connection&) = delete; + connection& operator=(const connection&) = delete; + + /// Construct a connection with the given socket. + explicit connection(asio::ip::tcp::socket socket, + request_handler& handler); + + /// Start the first asynchronous operation for the connection. + void start(); + +private: + /// Perform an asynchronous read operation. + void do_read(); + + /// Perform an asynchronous write operation. + void do_write(); + + /// Socket for the connection. + asio::ip::tcp::socket socket_; + + /// The handler used to process the incoming request. + request_handler& request_handler_; + + /// Buffer for incoming data. + std::array<char, 8192> buffer_; + + /// The incoming request. + request request_; + + /// The parser for the incoming request. + request_parser request_parser_; + + /// The reply to be sent back to the client. + reply reply_; +}; + +typedef std::shared_ptr<connection> connection_ptr; + +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_CONNECTION_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/header.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/header.hpp new file mode 100644 index 00000000000..8ab5d145a6d --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/header.hpp @@ -0,0 +1,28 @@ +// +// header.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_HEADER_HPP +#define HTTP_SERVER3_HEADER_HPP + +#include <string> + +namespace http { +namespace server3 { + +struct header +{ + std::string name; + std::string value; +}; + +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_HEADER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/main.cpp b/3rdparty/asio/src/examples/cpp11/http/server3/main.cpp new file mode 100644 index 00000000000..243de69bc75 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/main.cpp @@ -0,0 +1,44 @@ +// +// main.cpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include <string> +#include <asio.hpp> +#include "server.hpp" + +int main(int argc, char* argv[]) +{ + try + { + // Check command line arguments. + if (argc != 5) + { + std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n"; + std::cerr << " For IPv4, try:\n"; + std::cerr << " receiver 0.0.0.0 80 1 .\n"; + std::cerr << " For IPv6, try:\n"; + std::cerr << " receiver 0::0 80 1 .\n"; + return 1; + } + + // Initialise the server. + std::size_t num_threads = std::stoi(argv[3]); + http::server3::server s(argv[1], argv[2], argv[4], num_threads); + + // Run the server until stopped. + s.run(); + } + catch (std::exception& e) + { + std::cerr << "exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/mime_types.cpp b/3rdparty/asio/src/examples/cpp11/http/server3/mime_types.cpp new file mode 100644 index 00000000000..d0d804c7caa --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/mime_types.cpp @@ -0,0 +1,46 @@ +// +// mime_types.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "mime_types.hpp" + +namespace http { +namespace server3 { +namespace mime_types { + +struct mapping +{ + const char* extension; + const char* mime_type; +} mappings[] = +{ + { "gif", "image/gif" }, + { "htm", "text/html" }, + { "html", "text/html" }, + { "jpg", "image/jpeg" }, + { "png", "image/png" }, + { 0, 0 } // Marks end of list. +}; + +std::string extension_to_type(const std::string& extension) +{ + for (mapping* m = mappings; m->extension; ++m) + { + if (m->extension == extension) + { + return m->mime_type; + } + } + + return "text/plain"; +} + +} // namespace mime_types +} // namespace server3 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/mime_types.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/mime_types.hpp new file mode 100644 index 00000000000..a144c8677e6 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/mime_types.hpp @@ -0,0 +1,27 @@ +// +// mime_types.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_MIME_TYPES_HPP +#define HTTP_SERVER3_MIME_TYPES_HPP + +#include <string> + +namespace http { +namespace server3 { +namespace mime_types { + +/// Convert a file extension into a MIME type. +std::string extension_to_type(const std::string& extension); + +} // namespace mime_types +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_MIME_TYPES_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/reply.cpp b/3rdparty/asio/src/examples/cpp11/http/server3/reply.cpp new file mode 100644 index 00000000000..4695d4a8da2 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/reply.cpp @@ -0,0 +1,255 @@ +// +// reply.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "reply.hpp" +#include <string> + +namespace http { +namespace server3 { + +namespace status_strings { + +const std::string ok = + "HTTP/1.0 200 OK\r\n"; +const std::string created = + "HTTP/1.0 201 Created\r\n"; +const std::string accepted = + "HTTP/1.0 202 Accepted\r\n"; +const std::string no_content = + "HTTP/1.0 204 No Content\r\n"; +const std::string multiple_choices = + "HTTP/1.0 300 Multiple Choices\r\n"; +const std::string moved_permanently = + "HTTP/1.0 301 Moved Permanently\r\n"; +const std::string moved_temporarily = + "HTTP/1.0 302 Moved Temporarily\r\n"; +const std::string not_modified = + "HTTP/1.0 304 Not Modified\r\n"; +const std::string bad_request = + "HTTP/1.0 400 Bad Request\r\n"; +const std::string unauthorized = + "HTTP/1.0 401 Unauthorized\r\n"; +const std::string forbidden = + "HTTP/1.0 403 Forbidden\r\n"; +const std::string not_found = + "HTTP/1.0 404 Not Found\r\n"; +const std::string internal_server_error = + "HTTP/1.0 500 Internal Server Error\r\n"; +const std::string not_implemented = + "HTTP/1.0 501 Not Implemented\r\n"; +const std::string bad_gateway = + "HTTP/1.0 502 Bad Gateway\r\n"; +const std::string service_unavailable = + "HTTP/1.0 503 Service Unavailable\r\n"; + +asio::const_buffer to_buffer(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return asio::buffer(ok); + case reply::created: + return asio::buffer(created); + case reply::accepted: + return asio::buffer(accepted); + case reply::no_content: + return asio::buffer(no_content); + case reply::multiple_choices: + return asio::buffer(multiple_choices); + case reply::moved_permanently: + return asio::buffer(moved_permanently); + case reply::moved_temporarily: + return asio::buffer(moved_temporarily); + case reply::not_modified: + return asio::buffer(not_modified); + case reply::bad_request: + return asio::buffer(bad_request); + case reply::unauthorized: + return asio::buffer(unauthorized); + case reply::forbidden: + return asio::buffer(forbidden); + case reply::not_found: + return asio::buffer(not_found); + case reply::internal_server_error: + return asio::buffer(internal_server_error); + case reply::not_implemented: + return asio::buffer(not_implemented); + case reply::bad_gateway: + return asio::buffer(bad_gateway); + case reply::service_unavailable: + return asio::buffer(service_unavailable); + default: + return asio::buffer(internal_server_error); + } +} + +} // namespace status_strings + +namespace misc_strings { + +const char name_value_separator[] = { ':', ' ' }; +const char crlf[] = { '\r', '\n' }; + +} // namespace misc_strings + +std::vector<asio::const_buffer> reply::to_buffers() +{ + std::vector<asio::const_buffer> buffers; + buffers.push_back(status_strings::to_buffer(status)); + for (std::size_t i = 0; i < headers.size(); ++i) + { + header& h = headers[i]; + buffers.push_back(asio::buffer(h.name)); + buffers.push_back(asio::buffer(misc_strings::name_value_separator)); + buffers.push_back(asio::buffer(h.value)); + buffers.push_back(asio::buffer(misc_strings::crlf)); + } + buffers.push_back(asio::buffer(misc_strings::crlf)); + buffers.push_back(asio::buffer(content)); + return buffers; +} + +namespace stock_replies { + +const char ok[] = ""; +const char created[] = + "<html>" + "<head><title>Created</title></head>" + "<body><h1>201 Created</h1></body>" + "</html>"; +const char accepted[] = + "<html>" + "<head><title>Accepted</title></head>" + "<body><h1>202 Accepted</h1></body>" + "</html>"; +const char no_content[] = + "<html>" + "<head><title>No Content</title></head>" + "<body><h1>204 Content</h1></body>" + "</html>"; +const char multiple_choices[] = + "<html>" + "<head><title>Multiple Choices</title></head>" + "<body><h1>300 Multiple Choices</h1></body>" + "</html>"; +const char moved_permanently[] = + "<html>" + "<head><title>Moved Permanently</title></head>" + "<body><h1>301 Moved Permanently</h1></body>" + "</html>"; +const char moved_temporarily[] = + "<html>" + "<head><title>Moved Temporarily</title></head>" + "<body><h1>302 Moved Temporarily</h1></body>" + "</html>"; +const char not_modified[] = + "<html>" + "<head><title>Not Modified</title></head>" + "<body><h1>304 Not Modified</h1></body>" + "</html>"; +const char bad_request[] = + "<html>" + "<head><title>Bad Request</title></head>" + "<body><h1>400 Bad Request</h1></body>" + "</html>"; +const char unauthorized[] = + "<html>" + "<head><title>Unauthorized</title></head>" + "<body><h1>401 Unauthorized</h1></body>" + "</html>"; +const char forbidden[] = + "<html>" + "<head><title>Forbidden</title></head>" + "<body><h1>403 Forbidden</h1></body>" + "</html>"; +const char not_found[] = + "<html>" + "<head><title>Not Found</title></head>" + "<body><h1>404 Not Found</h1></body>" + "</html>"; +const char internal_server_error[] = + "<html>" + "<head><title>Internal Server Error</title></head>" + "<body><h1>500 Internal Server Error</h1></body>" + "</html>"; +const char not_implemented[] = + "<html>" + "<head><title>Not Implemented</title></head>" + "<body><h1>501 Not Implemented</h1></body>" + "</html>"; +const char bad_gateway[] = + "<html>" + "<head><title>Bad Gateway</title></head>" + "<body><h1>502 Bad Gateway</h1></body>" + "</html>"; +const char service_unavailable[] = + "<html>" + "<head><title>Service Unavailable</title></head>" + "<body><h1>503 Service Unavailable</h1></body>" + "</html>"; + +std::string to_string(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return ok; + case reply::created: + return created; + case reply::accepted: + return accepted; + case reply::no_content: + return no_content; + case reply::multiple_choices: + return multiple_choices; + case reply::moved_permanently: + return moved_permanently; + case reply::moved_temporarily: + return moved_temporarily; + case reply::not_modified: + return not_modified; + case reply::bad_request: + return bad_request; + case reply::unauthorized: + return unauthorized; + case reply::forbidden: + return forbidden; + case reply::not_found: + return not_found; + case reply::internal_server_error: + return internal_server_error; + case reply::not_implemented: + return not_implemented; + case reply::bad_gateway: + return bad_gateway; + case reply::service_unavailable: + return service_unavailable; + default: + return internal_server_error; + } +} + +} // namespace stock_replies + +reply reply::stock_reply(reply::status_type status) +{ + reply rep; + rep.status = status; + rep.content = stock_replies::to_string(status); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "text/html"; + return rep; +} + +} // namespace server3 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/reply.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/reply.hpp new file mode 100644 index 00000000000..fd9c7ed9ed5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/reply.hpp @@ -0,0 +1,64 @@ +// +// reply.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_REPLY_HPP +#define HTTP_SERVER3_REPLY_HPP + +#include <string> +#include <vector> +#include <asio.hpp> +#include "header.hpp" + +namespace http { +namespace server3 { + +/// A reply to be sent to a client. +struct reply +{ + /// The status of the reply. + enum status_type + { + ok = 200, + created = 201, + accepted = 202, + no_content = 204, + multiple_choices = 300, + moved_permanently = 301, + moved_temporarily = 302, + not_modified = 304, + bad_request = 400, + unauthorized = 401, + forbidden = 403, + not_found = 404, + internal_server_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503 + } status; + + /// The headers to be included in the reply. + std::vector<header> headers; + + /// The content to be sent in the reply. + std::string content; + + /// Convert the reply into a vector of buffers. The buffers do not own the + /// underlying memory blocks, therefore the reply object must remain valid and + /// not be changed until the write operation has completed. + std::vector<asio::const_buffer> to_buffers(); + + /// Get a stock reply. + static reply stock_reply(status_type status); +}; + +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_REPLY_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/request.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/request.hpp new file mode 100644 index 00000000000..89a2f285b7a --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/request.hpp @@ -0,0 +1,34 @@ +// +// request.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_REQUEST_HPP +#define HTTP_SERVER3_REQUEST_HPP + +#include <string> +#include <vector> +#include "header.hpp" + +namespace http { +namespace server3 { + +/// A request received from a client. +struct request +{ + std::string method; + std::string uri; + int http_version_major; + int http_version_minor; + std::vector<header> headers; +}; + +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_REQUEST_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/request_handler.cpp b/3rdparty/asio/src/examples/cpp11/http/server3/request_handler.cpp new file mode 100644 index 00000000000..bdc6bd60892 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/request_handler.cpp @@ -0,0 +1,121 @@ +// +// request_handler.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "request_handler.hpp" +#include <fstream> +#include <sstream> +#include <string> +#include "mime_types.hpp" +#include "reply.hpp" +#include "request.hpp" + +namespace http { +namespace server3 { + +request_handler::request_handler(const std::string& doc_root) + : doc_root_(doc_root) +{ +} + +void request_handler::handle_request(const request& req, reply& rep) +{ + // Decode url to path. + std::string request_path; + if (!url_decode(req.uri, request_path)) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // Request path must be absolute and not contain "..". + if (request_path.empty() || request_path[0] != '/' + || request_path.find("..") != std::string::npos) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // If path ends in slash (i.e. is a directory) then add "index.html". + if (request_path[request_path.size() - 1] == '/') + { + request_path += "index.html"; + } + + // Determine the file extension. + std::size_t last_slash_pos = request_path.find_last_of("/"); + std::size_t last_dot_pos = request_path.find_last_of("."); + std::string extension; + if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) + { + extension = request_path.substr(last_dot_pos + 1); + } + + // Open the file to send back. + std::string full_path = doc_root_ + request_path; + std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); + if (!is) + { + rep = reply::stock_reply(reply::not_found); + return; + } + + // Fill out the reply to be sent to the client. + rep.status = reply::ok; + char buf[512]; + while (is.read(buf, sizeof(buf)).gcount() > 0) + rep.content.append(buf, is.gcount()); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = mime_types::extension_to_type(extension); +} + +bool request_handler::url_decode(const std::string& in, std::string& out) +{ + out.clear(); + out.reserve(in.size()); + for (std::size_t i = 0; i < in.size(); ++i) + { + if (in[i] == '%') + { + if (i + 3 <= in.size()) + { + int value = 0; + std::istringstream is(in.substr(i + 1, 2)); + if (is >> std::hex >> value) + { + out += static_cast<char>(value); + i += 2; + } + else + { + return false; + } + } + else + { + return false; + } + } + else if (in[i] == '+') + { + out += ' '; + } + else + { + out += in[i]; + } + } + return true; +} + +} // namespace server3 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/request_handler.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/request_handler.hpp new file mode 100644 index 00000000000..e3fe84ed0cb --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/request_handler.hpp @@ -0,0 +1,47 @@ +// +// request_handler.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_REQUEST_HANDLER_HPP +#define HTTP_SERVER3_REQUEST_HANDLER_HPP + +#include <string> + +namespace http { +namespace server3 { + +struct reply; +struct request; + +/// The common handler for all incoming requests. +class request_handler +{ +public: + request_handler(const request_handler&) = delete; + request_handler& operator=(const request_handler&) = delete; + + /// Construct with a directory containing files to be served. + explicit request_handler(const std::string& doc_root); + + /// Handle a request and produce a reply. + void handle_request(const request& req, reply& rep); + +private: + /// The directory containing the files to be served. + std::string doc_root_; + + /// Perform URL-decoding on a string. Returns false if the encoding was + /// invalid. + static bool url_decode(const std::string& in, std::string& out); +}; + +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_REQUEST_HANDLER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/request_parser.cpp b/3rdparty/asio/src/examples/cpp11/http/server3/request_parser.cpp new file mode 100644 index 00000000000..9fb6424fad7 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/request_parser.cpp @@ -0,0 +1,315 @@ +// +// request_parser.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "request_parser.hpp" +#include "request.hpp" + +namespace http { +namespace server3 { + +request_parser::request_parser() + : state_(method_start) +{ +} + +void request_parser::reset() +{ + state_ = method_start; +} + +request_parser::result_type request_parser::consume(request& req, char input) +{ + switch (state_) + { + case method_start: + if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + state_ = method; + req.method.push_back(input); + return indeterminate; + } + case method: + if (input == ' ') + { + state_ = uri; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.method.push_back(input); + return indeterminate; + } + case uri: + if (input == ' ') + { + state_ = http_version_h; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.uri.push_back(input); + return indeterminate; + } + case http_version_h: + if (input == 'H') + { + state_ = http_version_t_1; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_1: + if (input == 'T') + { + state_ = http_version_t_2; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_2: + if (input == 'T') + { + state_ = http_version_p; + return indeterminate; + } + else + { + return bad; + } + case http_version_p: + if (input == 'P') + { + state_ = http_version_slash; + return indeterminate; + } + else + { + return bad; + } + case http_version_slash: + if (input == '/') + { + req.http_version_major = 0; + req.http_version_minor = 0; + state_ = http_version_major_start; + return indeterminate; + } + else + { + return bad; + } + case http_version_major_start: + if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + state_ = http_version_major; + return indeterminate; + } + else + { + return bad; + } + case http_version_major: + if (input == '.') + { + state_ = http_version_minor_start; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor_start: + if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + state_ = http_version_minor; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor: + if (input == '\r') + { + state_ = expecting_newline_1; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_1: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case header_line_start: + if (input == '\r') + { + state_ = expecting_newline_3; + return indeterminate; + } + else if (!req.headers.empty() && (input == ' ' || input == '\t')) + { + state_ = header_lws; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.push_back(header()); + req.headers.back().name.push_back(input); + state_ = header_name; + return indeterminate; + } + case header_lws: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (input == ' ' || input == '\t') + { + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + state_ = header_value; + req.headers.back().value.push_back(input); + return indeterminate; + } + case header_name: + if (input == ':') + { + state_ = space_before_header_value; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.back().name.push_back(input); + return indeterminate; + } + case space_before_header_value: + if (input == ' ') + { + state_ = header_value; + return indeterminate; + } + else + { + return bad; + } + case header_value: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.headers.back().value.push_back(input); + return indeterminate; + } + case expecting_newline_2: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_3: + return (input == '\n') ? good : bad; + default: + return bad; + } +} + +bool request_parser::is_char(int c) +{ + return c >= 0 && c <= 127; +} + +bool request_parser::is_ctl(int c) +{ + return (c >= 0 && c <= 31) || (c == 127); +} + +bool request_parser::is_tspecial(int c) +{ + switch (c) + { + case '(': case ')': case '<': case '>': case '@': + case ',': case ';': case ':': case '\\': case '"': + case '/': case '[': case ']': case '?': case '=': + case '{': case '}': case ' ': case '\t': + return true; + default: + return false; + } +} + +bool request_parser::is_digit(int c) +{ + return c >= '0' && c <= '9'; +} + +} // namespace server3 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/request_parser.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/request_parser.hpp new file mode 100644 index 00000000000..a8334ed13ee --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/request_parser.hpp @@ -0,0 +1,96 @@ +// +// request_parser.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_REQUEST_PARSER_HPP +#define HTTP_SERVER3_REQUEST_PARSER_HPP + +#include <tuple> + +namespace http { +namespace server3 { + +struct request; + +/// Parser for incoming requests. +class request_parser +{ +public: + /// Construct ready to parse the request method. + request_parser(); + + /// Reset to initial parser state. + void reset(); + + /// Result of parse. + enum result_type { good, bad, indeterminate }; + + /// Parse some data. The enum return value is good when a complete request has + /// been parsed, bad if the data is invalid, indeterminate when more data is + /// required. The InputIterator return value indicates how much of the input + /// has been consumed. + template <typename InputIterator> + std::tuple<result_type, InputIterator> parse(request& req, + InputIterator begin, InputIterator end) + { + while (begin != end) + { + result_type result = consume(req, *begin++); + if (result == good || result == bad) + return std::make_tuple(result, begin); + } + return std::make_tuple(indeterminate, begin); + } + +private: + /// Handle the next character of input. + result_type consume(request& req, char input); + + /// Check if a byte is an HTTP character. + static bool is_char(int c); + + /// Check if a byte is an HTTP control character. + static bool is_ctl(int c); + + /// Check if a byte is defined as an HTTP tspecial character. + static bool is_tspecial(int c); + + /// Check if a byte is a digit. + static bool is_digit(int c); + + /// The current state of the parser. + enum state + { + method_start, + method, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + expecting_newline_2, + expecting_newline_3 + } state_; +}; + +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_REQUEST_PARSER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/server.cpp b/3rdparty/asio/src/examples/cpp11/http/server3/server.cpp new file mode 100644 index 00000000000..c8da4b4f4db --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/server.cpp @@ -0,0 +1,97 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "server.hpp" +#include <signal.h> +#include <thread> +#include <utility> +#include <vector> +#include "connection.hpp" + +namespace http { +namespace server3 { + +server::server(const std::string& address, const std::string& port, + const std::string& doc_root, std::size_t thread_pool_size) + : thread_pool_size_(thread_pool_size), + signals_(io_context_), + acceptor_(io_context_), + request_handler_(doc_root) +{ + // Register to handle the signals that indicate when the server should exit. + // It is safe to register for the same signal multiple times in a program, + // provided all registration for the specified signal is made through Asio. + signals_.add(SIGINT); + signals_.add(SIGTERM); +#if defined(SIGQUIT) + signals_.add(SIGQUIT); +#endif // defined(SIGQUIT) + + do_await_stop(); + + // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). + asio::ip::tcp::resolver resolver(io_context_); + asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); + acceptor_.open(endpoint.protocol()); + acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true)); + acceptor_.bind(endpoint); + acceptor_.listen(); + + do_accept(); +} + +void server::run() +{ + // Create a pool of threads to run the io_context. + std::vector<std::thread> threads; + for (std::size_t i = 0; i < thread_pool_size_; ++i) + threads.emplace_back([this]{ io_context_.run(); }); + + // Wait for all threads in the pool to exit. + for (std::size_t i = 0; i < threads.size(); ++i) + threads[i].join(); +} + +void server::do_accept() +{ + // The newly accepted socket is put into its own strand to ensure that all + // completion handlers associated with the connection do not run concurrently. + acceptor_.async_accept(asio::make_strand(io_context_), + [this](std::error_code ec, asio::ip::tcp::socket socket) + { + // Check whether the server was stopped by a signal before this + // completion handler had a chance to run. + if (!acceptor_.is_open()) + { + return; + } + + if (!ec) + { + std::make_shared<connection>( + std::move(socket), request_handler_)->start(); + } + + do_accept(); + }); +} + +void server::do_await_stop() +{ + signals_.async_wait( + [this](std::error_code /*ec*/, int /*signo*/) + { + io_context_.stop(); + }); +} + +} // namespace server3 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server3/server.hpp b/3rdparty/asio/src/examples/cpp11/http/server3/server.hpp new file mode 100644 index 00000000000..2948cadbf17 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server3/server.hpp @@ -0,0 +1,62 @@ +// +// server.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER3_SERVER_HPP +#define HTTP_SERVER3_SERVER_HPP + +#include <asio.hpp> +#include <string> +#include "request_handler.hpp" + +namespace http { +namespace server3 { + +/// The top-level class of the HTTP server. +class server +{ +public: + server(const server&) = delete; + server& operator=(const server&) = delete; + + /// Construct the server to listen on the specified TCP address and port, and + /// serve up files from the given directory. + explicit server(const std::string& address, const std::string& port, + const std::string& doc_root, std::size_t thread_pool_size); + + /// Run the server's io_context loop. + void run(); + +private: + /// Perform an asynchronous accept operation. + void do_accept(); + + /// Wait for a request to stop the server. + void do_await_stop(); + + /// The number of threads that will call io_context::run(). + std::size_t thread_pool_size_; + + /// The io_context used to perform asynchronous operations. + asio::io_context io_context_; + + /// The signal_set is used to register for process termination notifications. + asio::signal_set signals_; + + /// Acceptor used to listen for incoming connections. + asio::ip::tcp::acceptor acceptor_; + + /// The handler for all incoming requests. + request_handler request_handler_; +}; + +} // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_SERVER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/file_handler.cpp b/3rdparty/asio/src/examples/cpp11/http/server4/file_handler.cpp new file mode 100644 index 00000000000..ad982e58b26 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/file_handler.cpp @@ -0,0 +1,121 @@ +// +// file_handler.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "file_handler.hpp" +#include <fstream> +#include <sstream> +#include <string> +#include "mime_types.hpp" +#include "reply.hpp" +#include "request.hpp" + +namespace http { +namespace server4 { + +file_handler::file_handler(const std::string& doc_root) + : doc_root_(doc_root) +{ +} + +void file_handler::operator()(const request& req, reply& rep) +{ + // Decode url to path. + std::string request_path; + if (!url_decode(req.uri, request_path)) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // Request path must be absolute and not contain "..". + if (request_path.empty() || request_path[0] != '/' + || request_path.find("..") != std::string::npos) + { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // If path ends in slash (i.e. is a directory) then add "index.html". + if (request_path[request_path.size() - 1] == '/') + { + request_path += "index.html"; + } + + // Determine the file extension. + std::size_t last_slash_pos = request_path.find_last_of("/"); + std::size_t last_dot_pos = request_path.find_last_of("."); + std::string extension; + if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) + { + extension = request_path.substr(last_dot_pos + 1); + } + + // Open the file to send back. + std::string full_path = doc_root_ + request_path; + std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); + if (!is) + { + rep = reply::stock_reply(reply::not_found); + return; + } + + // Fill out the reply to be sent to the client. + rep.status = reply::ok; + char buf[512]; + while (is.read(buf, sizeof(buf)).gcount() > 0) + rep.content.append(buf, is.gcount()); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = mime_types::extension_to_type(extension); +} + +bool file_handler::url_decode(const std::string& in, std::string& out) +{ + out.clear(); + out.reserve(in.size()); + for (std::size_t i = 0; i < in.size(); ++i) + { + if (in[i] == '%') + { + if (i + 3 <= in.size()) + { + int value = 0; + std::istringstream is(in.substr(i + 1, 2)); + if (is >> std::hex >> value) + { + out += static_cast<char>(value); + i += 2; + } + else + { + return false; + } + } + else + { + return false; + } + } + else if (in[i] == '+') + { + out += ' '; + } + else + { + out += in[i]; + } + } + return true; +} + +} // namespace server4 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/file_handler.hpp b/3rdparty/asio/src/examples/cpp11/http/server4/file_handler.hpp new file mode 100644 index 00000000000..a16e5b6905c --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/file_handler.hpp @@ -0,0 +1,44 @@ +// +// file_handler.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER4_FILE_HANDLER_HPP +#define HTTP_SERVER4_FILE_HANDLER_HPP + +#include <string> + +namespace http { +namespace server4 { + +struct reply; +struct request; + +/// The common handler for all incoming requests. +class file_handler +{ +public: + /// Construct with a directory containing files to be served. + explicit file_handler(const std::string& doc_root); + + /// Handle a request and produce a reply. + void operator()(const request& req, reply& rep); + +private: + /// The directory containing the files to be served. + std::string doc_root_; + + /// Perform URL-decoding on a string. Returns false if the encoding was + /// invalid. + static bool url_decode(const std::string& in, std::string& out); +}; + +} // namespace server4 +} // namespace http + +#endif // HTTP_SERVER4_FILE_HANDLER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/header.hpp b/3rdparty/asio/src/examples/cpp11/http/server4/header.hpp new file mode 100644 index 00000000000..a4148e5d910 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/header.hpp @@ -0,0 +1,28 @@ +// +// header.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER4_HEADER_HPP +#define HTTP_SERVER4_HEADER_HPP + +#include <string> + +namespace http { +namespace server4 { + +struct header +{ + std::string name; + std::string value; +}; + +} // namespace server4 +} // namespace http + +#endif // HTTP_SERVER4_HEADER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/main.cpp b/3rdparty/asio/src/examples/cpp11/http/server4/main.cpp new file mode 100644 index 00000000000..29706e6a335 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/main.cpp @@ -0,0 +1,60 @@ +// +// main.cpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include <asio.hpp> +#include <signal.h> +#include "server.hpp" +#include "file_handler.hpp" + +int main(int argc, char* argv[]) +{ + try + { + // Check command line arguments. + if (argc != 4) + { + std::cerr << "Usage: http_server <address> <port> <doc_root>\n"; + std::cerr << " For IPv4, try:\n"; + std::cerr << " receiver 0.0.0.0 80 .\n"; + std::cerr << " For IPv6, try:\n"; + std::cerr << " receiver 0::0 80 .\n"; + return 1; + } + + asio::io_context io_context; + + // Launch the initial server coroutine. + http::server4::server(io_context, argv[1], argv[2], + http::server4::file_handler(argv[3]))(); + + // Wait for signals indicating time to shut down. + asio::signal_set signals(io_context); + signals.add(SIGINT); + signals.add(SIGTERM); +#if defined(SIGQUIT) + signals.add(SIGQUIT); +#endif // defined(SIGQUIT) + signals.async_wait( + [&io_context](std::error_code, int) + { + io_context.stop(); + }); + + // Run the server. + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << "exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/mime_types.cpp b/3rdparty/asio/src/examples/cpp11/http/server4/mime_types.cpp new file mode 100644 index 00000000000..6cf11e383d8 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/mime_types.cpp @@ -0,0 +1,46 @@ +// +// mime_types.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "mime_types.hpp" + +namespace http { +namespace server4 { +namespace mime_types { + +struct mapping +{ + const char* extension; + const char* mime_type; +} mappings[] = +{ + { "gif", "image/gif" }, + { "htm", "text/html" }, + { "html", "text/html" }, + { "jpg", "image/jpeg" }, + { "png", "image/png" }, + { 0, 0 } // Marks end of list. +}; + +std::string extension_to_type(const std::string& extension) +{ + for (mapping* m = mappings; m->extension; ++m) + { + if (m->extension == extension) + { + return m->mime_type; + } + } + + return "text/plain"; +} + +} // namespace mime_types +} // namespace server4 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/mime_types.hpp b/3rdparty/asio/src/examples/cpp11/http/server4/mime_types.hpp new file mode 100644 index 00000000000..6086fce22eb --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/mime_types.hpp @@ -0,0 +1,27 @@ +// +// mime_types.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER4_MIME_TYPES_HPP +#define HTTP_SERVER4_MIME_TYPES_HPP + +#include <string> + +namespace http { +namespace server4 { +namespace mime_types { + +/// Convert a file extension into a MIME type. +std::string extension_to_type(const std::string& extension); + +} // namespace mime_types +} // namespace server4 +} // namespace http + +#endif // HTTP_SERVER4_MIME_TYPES_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/reply.cpp b/3rdparty/asio/src/examples/cpp11/http/server4/reply.cpp new file mode 100644 index 00000000000..4e5752ea7d0 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/reply.cpp @@ -0,0 +1,255 @@ +// +// reply.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "reply.hpp" +#include <string> + +namespace http { +namespace server4 { + +namespace status_strings { + +const std::string ok = + "HTTP/1.0 200 OK\r\n"; +const std::string created = + "HTTP/1.0 201 Created\r\n"; +const std::string accepted = + "HTTP/1.0 202 Accepted\r\n"; +const std::string no_content = + "HTTP/1.0 204 No Content\r\n"; +const std::string multiple_choices = + "HTTP/1.0 300 Multiple Choices\r\n"; +const std::string moved_permanently = + "HTTP/1.0 301 Moved Permanently\r\n"; +const std::string moved_temporarily = + "HTTP/1.0 302 Moved Temporarily\r\n"; +const std::string not_modified = + "HTTP/1.0 304 Not Modified\r\n"; +const std::string bad_request = + "HTTP/1.0 400 Bad Request\r\n"; +const std::string unauthorized = + "HTTP/1.0 401 Unauthorized\r\n"; +const std::string forbidden = + "HTTP/1.0 403 Forbidden\r\n"; +const std::string not_found = + "HTTP/1.0 404 Not Found\r\n"; +const std::string internal_server_error = + "HTTP/1.0 500 Internal Server Error\r\n"; +const std::string not_implemented = + "HTTP/1.0 501 Not Implemented\r\n"; +const std::string bad_gateway = + "HTTP/1.0 502 Bad Gateway\r\n"; +const std::string service_unavailable = + "HTTP/1.0 503 Service Unavailable\r\n"; + +asio::const_buffer to_buffer(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return asio::buffer(ok); + case reply::created: + return asio::buffer(created); + case reply::accepted: + return asio::buffer(accepted); + case reply::no_content: + return asio::buffer(no_content); + case reply::multiple_choices: + return asio::buffer(multiple_choices); + case reply::moved_permanently: + return asio::buffer(moved_permanently); + case reply::moved_temporarily: + return asio::buffer(moved_temporarily); + case reply::not_modified: + return asio::buffer(not_modified); + case reply::bad_request: + return asio::buffer(bad_request); + case reply::unauthorized: + return asio::buffer(unauthorized); + case reply::forbidden: + return asio::buffer(forbidden); + case reply::not_found: + return asio::buffer(not_found); + case reply::internal_server_error: + return asio::buffer(internal_server_error); + case reply::not_implemented: + return asio::buffer(not_implemented); + case reply::bad_gateway: + return asio::buffer(bad_gateway); + case reply::service_unavailable: + return asio::buffer(service_unavailable); + default: + return asio::buffer(internal_server_error); + } +} + +} // namespace status_strings + +namespace misc_strings { + +const char name_value_separator[] = { ':', ' ' }; +const char crlf[] = { '\r', '\n' }; + +} // namespace misc_strings + +std::vector<asio::const_buffer> reply::to_buffers() +{ + std::vector<asio::const_buffer> buffers; + buffers.push_back(status_strings::to_buffer(status)); + for (std::size_t i = 0; i < headers.size(); ++i) + { + header& h = headers[i]; + buffers.push_back(asio::buffer(h.name)); + buffers.push_back(asio::buffer(misc_strings::name_value_separator)); + buffers.push_back(asio::buffer(h.value)); + buffers.push_back(asio::buffer(misc_strings::crlf)); + } + buffers.push_back(asio::buffer(misc_strings::crlf)); + buffers.push_back(asio::buffer(content)); + return buffers; +} + +namespace stock_replies { + +const char ok[] = ""; +const char created[] = + "<html>" + "<head><title>Created</title></head>" + "<body><h1>201 Created</h1></body>" + "</html>"; +const char accepted[] = + "<html>" + "<head><title>Accepted</title></head>" + "<body><h1>202 Accepted</h1></body>" + "</html>"; +const char no_content[] = + "<html>" + "<head><title>No Content</title></head>" + "<body><h1>204 Content</h1></body>" + "</html>"; +const char multiple_choices[] = + "<html>" + "<head><title>Multiple Choices</title></head>" + "<body><h1>300 Multiple Choices</h1></body>" + "</html>"; +const char moved_permanently[] = + "<html>" + "<head><title>Moved Permanently</title></head>" + "<body><h1>301 Moved Permanently</h1></body>" + "</html>"; +const char moved_temporarily[] = + "<html>" + "<head><title>Moved Temporarily</title></head>" + "<body><h1>302 Moved Temporarily</h1></body>" + "</html>"; +const char not_modified[] = + "<html>" + "<head><title>Not Modified</title></head>" + "<body><h1>304 Not Modified</h1></body>" + "</html>"; +const char bad_request[] = + "<html>" + "<head><title>Bad Request</title></head>" + "<body><h1>400 Bad Request</h1></body>" + "</html>"; +const char unauthorized[] = + "<html>" + "<head><title>Unauthorized</title></head>" + "<body><h1>401 Unauthorized</h1></body>" + "</html>"; +const char forbidden[] = + "<html>" + "<head><title>Forbidden</title></head>" + "<body><h1>403 Forbidden</h1></body>" + "</html>"; +const char not_found[] = + "<html>" + "<head><title>Not Found</title></head>" + "<body><h1>404 Not Found</h1></body>" + "</html>"; +const char internal_server_error[] = + "<html>" + "<head><title>Internal Server Error</title></head>" + "<body><h1>500 Internal Server Error</h1></body>" + "</html>"; +const char not_implemented[] = + "<html>" + "<head><title>Not Implemented</title></head>" + "<body><h1>501 Not Implemented</h1></body>" + "</html>"; +const char bad_gateway[] = + "<html>" + "<head><title>Bad Gateway</title></head>" + "<body><h1>502 Bad Gateway</h1></body>" + "</html>"; +const char service_unavailable[] = + "<html>" + "<head><title>Service Unavailable</title></head>" + "<body><h1>503 Service Unavailable</h1></body>" + "</html>"; + +std::string to_string(reply::status_type status) +{ + switch (status) + { + case reply::ok: + return ok; + case reply::created: + return created; + case reply::accepted: + return accepted; + case reply::no_content: + return no_content; + case reply::multiple_choices: + return multiple_choices; + case reply::moved_permanently: + return moved_permanently; + case reply::moved_temporarily: + return moved_temporarily; + case reply::not_modified: + return not_modified; + case reply::bad_request: + return bad_request; + case reply::unauthorized: + return unauthorized; + case reply::forbidden: + return forbidden; + case reply::not_found: + return not_found; + case reply::internal_server_error: + return internal_server_error; + case reply::not_implemented: + return not_implemented; + case reply::bad_gateway: + return bad_gateway; + case reply::service_unavailable: + return service_unavailable; + default: + return internal_server_error; + } +} + +} // namespace stock_replies + +reply reply::stock_reply(reply::status_type status) +{ + reply rep; + rep.status = status; + rep.content = stock_replies::to_string(status); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = std::to_string(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "text/html"; + return rep; +} + +} // namespace server4 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/reply.hpp b/3rdparty/asio/src/examples/cpp11/http/server4/reply.hpp new file mode 100644 index 00000000000..d08579a3339 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/reply.hpp @@ -0,0 +1,64 @@ +// +// reply.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER4_REPLY_HPP +#define HTTP_SERVER4_REPLY_HPP + +#include <string> +#include <vector> +#include <asio.hpp> +#include "header.hpp" + +namespace http { +namespace server4 { + +/// A reply to be sent to a client. +struct reply +{ + /// The status of the reply. + enum status_type + { + ok = 200, + created = 201, + accepted = 202, + no_content = 204, + multiple_choices = 300, + moved_permanently = 301, + moved_temporarily = 302, + not_modified = 304, + bad_request = 400, + unauthorized = 401, + forbidden = 403, + not_found = 404, + internal_server_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503 + } status; + + /// The headers to be included in the reply. + std::vector<header> headers; + + /// The content to be sent in the reply. + std::string content; + + /// Convert the reply into a vector of buffers. The buffers do not own the + /// underlying memory blocks, therefore the reply object must remain valid and + /// not be changed until the write operation has completed. + std::vector<asio::const_buffer> to_buffers(); + + /// Get a stock reply. + static reply stock_reply(status_type status); +}; + +} // namespace server4 +} // namespace http + +#endif // HTTP_SERVER4_REPLY_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/request.hpp b/3rdparty/asio/src/examples/cpp11/http/server4/request.hpp new file mode 100644 index 00000000000..8b20c4db0db --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/request.hpp @@ -0,0 +1,34 @@ +// +// request.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER4_REQUEST_HPP +#define HTTP_SERVER4_REQUEST_HPP + +#include <string> +#include <vector> +#include "header.hpp" + +namespace http { +namespace server4 { + +/// A request received from a client. +struct request +{ + std::string method; + std::string uri; + int http_version_major; + int http_version_minor; + std::vector<header> headers; +}; + +} // namespace server4 +} // namespace http + +#endif // HTTP_SERVER4_REQUEST_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/request_parser.cpp b/3rdparty/asio/src/examples/cpp11/http/server4/request_parser.cpp new file mode 100644 index 00000000000..ec557fccdd6 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/request_parser.cpp @@ -0,0 +1,315 @@ +// +// request_parser.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "request_parser.hpp" +#include "request.hpp" + +namespace http { +namespace server4 { + +request_parser::request_parser() + : state_(method_start) +{ +} + +void request_parser::reset() +{ + state_ = method_start; +} + +request_parser::result_type request_parser::consume(request& req, char input) +{ + switch (state_) + { + case method_start: + if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + state_ = method; + req.method.push_back(input); + return indeterminate; + } + case method: + if (input == ' ') + { + state_ = uri; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.method.push_back(input); + return indeterminate; + } + case uri: + if (input == ' ') + { + state_ = http_version_h; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.uri.push_back(input); + return indeterminate; + } + case http_version_h: + if (input == 'H') + { + state_ = http_version_t_1; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_1: + if (input == 'T') + { + state_ = http_version_t_2; + return indeterminate; + } + else + { + return bad; + } + case http_version_t_2: + if (input == 'T') + { + state_ = http_version_p; + return indeterminate; + } + else + { + return bad; + } + case http_version_p: + if (input == 'P') + { + state_ = http_version_slash; + return indeterminate; + } + else + { + return bad; + } + case http_version_slash: + if (input == '/') + { + req.http_version_major = 0; + req.http_version_minor = 0; + state_ = http_version_major_start; + return indeterminate; + } + else + { + return bad; + } + case http_version_major_start: + if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + state_ = http_version_major; + return indeterminate; + } + else + { + return bad; + } + case http_version_major: + if (input == '.') + { + state_ = http_version_minor_start; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_major = req.http_version_major * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor_start: + if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + state_ = http_version_minor; + return indeterminate; + } + else + { + return bad; + } + case http_version_minor: + if (input == '\r') + { + state_ = expecting_newline_1; + return indeterminate; + } + else if (is_digit(input)) + { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_1: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case header_line_start: + if (input == '\r') + { + state_ = expecting_newline_3; + return indeterminate; + } + else if (!req.headers.empty() && (input == ' ' || input == '\t')) + { + state_ = header_lws; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.push_back(header()); + req.headers.back().name.push_back(input); + state_ = header_name; + return indeterminate; + } + case header_lws: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (input == ' ' || input == '\t') + { + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + state_ = header_value; + req.headers.back().value.push_back(input); + return indeterminate; + } + case header_name: + if (input == ':') + { + state_ = space_before_header_value; + return indeterminate; + } + else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) + { + return bad; + } + else + { + req.headers.back().name.push_back(input); + return indeterminate; + } + case space_before_header_value: + if (input == ' ') + { + state_ = header_value; + return indeterminate; + } + else + { + return bad; + } + case header_value: + if (input == '\r') + { + state_ = expecting_newline_2; + return indeterminate; + } + else if (is_ctl(input)) + { + return bad; + } + else + { + req.headers.back().value.push_back(input); + return indeterminate; + } + case expecting_newline_2: + if (input == '\n') + { + state_ = header_line_start; + return indeterminate; + } + else + { + return bad; + } + case expecting_newline_3: + return (input == '\n') ? good : bad; + default: + return bad; + } +} + +bool request_parser::is_char(int c) +{ + return c >= 0 && c <= 127; +} + +bool request_parser::is_ctl(int c) +{ + return (c >= 0 && c <= 31) || (c == 127); +} + +bool request_parser::is_tspecial(int c) +{ + switch (c) + { + case '(': case ')': case '<': case '>': case '@': + case ',': case ';': case ':': case '\\': case '"': + case '/': case '[': case ']': case '?': case '=': + case '{': case '}': case ' ': case '\t': + return true; + default: + return false; + } +} + +bool request_parser::is_digit(int c) +{ + return c >= '0' && c <= '9'; +} + +} // namespace server4 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/request_parser.hpp b/3rdparty/asio/src/examples/cpp11/http/server4/request_parser.hpp new file mode 100644 index 00000000000..4129c489b51 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/request_parser.hpp @@ -0,0 +1,96 @@ +// +// request_parser.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER4_REQUEST_PARSER_HPP +#define HTTP_SERVER4_REQUEST_PARSER_HPP + +#include <tuple> + +namespace http { +namespace server4 { + +struct request; + +/// Parser for incoming requests. +class request_parser +{ +public: + /// Construct ready to parse the request method. + request_parser(); + + /// Reset to initial parser state. + void reset(); + + /// Result of parse. + enum result_type { good, bad, indeterminate }; + + /// Parse some data. The enum return value is good when a complete request has + /// been parsed, bad if the data is invalid, indeterminate when more data is + /// required. The InputIterator return value indicates how much of the input + /// has been consumed. + template <typename InputIterator> + std::tuple<result_type, InputIterator> parse(request& req, + InputIterator begin, InputIterator end) + { + while (begin != end) + { + result_type result = consume(req, *begin++); + if (result == good || result == bad) + return std::make_tuple(result, begin); + } + return std::make_tuple(indeterminate, begin); + } + +private: + /// Handle the next character of input. + result_type consume(request& req, char input); + + /// Check if a byte is an HTTP character. + static bool is_char(int c); + + /// Check if a byte is an HTTP control character. + static bool is_ctl(int c); + + /// Check if a byte is defined as an HTTP tspecial character. + static bool is_tspecial(int c); + + /// Check if a byte is a digit. + static bool is_digit(int c); + + /// The current state of the parser. + enum state + { + method_start, + method, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + expecting_newline_2, + expecting_newline_3 + } state_; +}; + +} // namespace server4 +} // namespace http + +#endif // HTTP_SERVER4_REQUEST_PARSER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/server.cpp b/3rdparty/asio/src/examples/cpp11/http/server4/server.cpp new file mode 100644 index 00000000000..9c75f75e982 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/server.cpp @@ -0,0 +1,122 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "server.hpp" +#include "request.hpp" +#include "reply.hpp" + +namespace http { +namespace server4 { + +server::server(asio::io_context& io_context, + const std::string& address, const std::string& port, + std::function<void(const request&, reply&)> request_handler) + : request_handler_(request_handler) +{ + tcp::resolver resolver(io_context); + asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); + acceptor_.reset(new tcp::acceptor(io_context, endpoint)); +} + +// Enable the pseudo-keywords reenter, yield and fork. +#include <asio/yield.hpp> + +void server::operator()(std::error_code ec, std::size_t length) +{ + // In this example we keep the error handling code in one place by + // hoisting it outside the coroutine. An alternative approach would be to + // check the value of ec after each yield for an asynchronous operation. + if (!ec) + { + // On reentering a coroutine, control jumps to the location of the last + // yield or fork. The argument to the "reenter" pseudo-keyword can be a + // pointer or reference to an object of type coroutine. + reenter (this) + { + // Loop to accept incoming connections. + do + { + // Create a new socket for the next incoming connection. + socket_.reset(new tcp::socket(acceptor_->get_executor())); + + // Accept a new connection. The "yield" pseudo-keyword saves the current + // line number and exits the coroutine's "reenter" block. We use the + // server coroutine as the completion handler for the async_accept + // operation. When the asynchronous operation completes, the io_context + // invokes the function call operator, we "reenter" the coroutine, and + // then control resumes at the following line. + yield acceptor_->async_accept(*socket_, *this); + + // We "fork" by cloning a new server coroutine to handle the connection. + // After forking we have a parent coroutine and a child coroutine. Both + // parent and child continue execution at the following line. They can + // be distinguished using the functions coroutine::is_parent() and + // coroutine::is_child(). + fork server(*this)(); + + // The parent continues looping to accept the next incoming connection. + // The child exits the loop and processes the connection. + } while (is_parent()); + + // Create the objects needed to receive a request on the connection. + buffer_.reset(new std::array<char, 8192>); + request_.reset(new request); + + // Loop until a complete request (or an invalid one) has been received. + do + { + // Receive some more data. When control resumes at the following line, + // the ec and length parameters reflect the result of the asynchronous + // operation. + yield socket_->async_read_some(asio::buffer(*buffer_), *this); + + // Parse the data we just received. + std::tie(parse_result_, std::ignore) + = request_parser_.parse(*request_, + buffer_->data(), buffer_->data() + length); + + // An indeterminate result means we need more data, so keep looping. + } while (parse_result_ == request_parser::indeterminate); + + // Create the reply object that will be sent back to the client. + reply_.reset(new reply); + + if (parse_result_ == request_parser::good) + { + // A valid request was received. Call the user-supplied function object + // to process the request and compose a reply. + request_handler_(*request_, *reply_); + } + else + { + // The request was invalid. + *reply_ = reply::stock_reply(reply::bad_request); + } + + // Send the reply back to the client. + yield asio::async_write(*socket_, reply_->to_buffers(), *this); + + // Initiate graceful connection closure. + socket_->shutdown(tcp::socket::shutdown_both, ec); + } + } + + // If an error occurs then the coroutine is not reentered. Consequently, no + // new asynchronous operations are started. This means that all shared_ptr + // references will disappear and the resources associated with the coroutine + // will be destroyed automatically after this function call returns. +} + +// Disable the pseudo-keywords reenter, yield and fork. +#include <asio/unyield.hpp> + +} // namespace server4 +} // namespace http diff --git a/3rdparty/asio/src/examples/cpp11/http/server4/server.hpp b/3rdparty/asio/src/examples/cpp11/http/server4/server.hpp new file mode 100644 index 00000000000..54d67832ba6 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/http/server4/server.hpp @@ -0,0 +1,73 @@ +// +// server.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 HTTP_SERVER4_SERVER_HPP +#define HTTP_SERVER4_SERVER_HPP + +#include <asio.hpp> +#include <array> +#include <functional> +#include <memory> +#include <string> +#include "request_parser.hpp" + +namespace http { +namespace server4 { + +struct request; +struct reply; + +/// The top-level coroutine of the HTTP server. +class server : asio::coroutine +{ +public: + /// Construct the server to listen on the specified TCP address and port, and + /// serve up files from the given directory. + explicit server(asio::io_context& io_context, + const std::string& address, const std::string& port, + std::function<void(const request&, reply&)> request_handler); + + /// Perform work associated with the server. + void operator()( + std::error_code ec = std::error_code(), + std::size_t length = 0); + +private: + typedef asio::ip::tcp tcp; + + /// The user-supplied handler for all incoming requests. + std::function<void(const request&, reply&)> request_handler_; + + /// Acceptor used to listen for incoming connections. + std::shared_ptr<tcp::acceptor> acceptor_; + + /// The current connection from a client. + std::shared_ptr<tcp::socket> socket_; + + /// Buffer for incoming data. + std::shared_ptr<std::array<char, 8192>> buffer_; + + /// The incoming request. + std::shared_ptr<request> request_; + + /// Whether the request is valid or not. + request_parser::result_type parse_result_; + + /// The parser for the incoming request. + request_parser request_parser_; + + /// The reply to be sent back to the client. + std::shared_ptr<reply> reply_; +}; + +} // namespace server4 +} // namespace http + +#endif // HTTP_SERVER4_SERVER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/icmp/icmp_header.hpp b/3rdparty/asio/src/examples/cpp11/icmp/icmp_header.hpp new file mode 100644 index 00000000000..369511c6267 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/icmp/icmp_header.hpp @@ -0,0 +1,94 @@ +// +// icmp_header.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 ICMP_HEADER_HPP +#define ICMP_HEADER_HPP + +#include <istream> +#include <ostream> +#include <algorithm> + +// ICMP header for both IPv4 and IPv6. +// +// The wire format of an ICMP header is: +// +// 0 8 16 31 +// +---------------+---------------+------------------------------+ --- +// | | | | ^ +// | type | code | checksum | | +// | | | | | +// +---------------+---------------+------------------------------+ 8 bytes +// | | | | +// | identifier | sequence number | | +// | | | v +// +-------------------------------+------------------------------+ --- + +class icmp_header +{ +public: + enum { echo_reply = 0, destination_unreachable = 3, source_quench = 4, + redirect = 5, echo_request = 8, time_exceeded = 11, parameter_problem = 12, + timestamp_request = 13, timestamp_reply = 14, info_request = 15, + info_reply = 16, address_request = 17, address_reply = 18 }; + + icmp_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); } + + unsigned char type() const { return rep_[0]; } + unsigned char code() const { return rep_[1]; } + unsigned short checksum() const { return decode(2, 3); } + unsigned short identifier() const { return decode(4, 5); } + unsigned short sequence_number() const { return decode(6, 7); } + + void type(unsigned char n) { rep_[0] = n; } + void code(unsigned char n) { rep_[1] = n; } + void checksum(unsigned short n) { encode(2, 3, n); } + void identifier(unsigned short n) { encode(4, 5, n); } + void sequence_number(unsigned short n) { encode(6, 7, n); } + + friend std::istream& operator>>(std::istream& is, icmp_header& header) + { return is.read(reinterpret_cast<char*>(header.rep_), 8); } + + friend std::ostream& operator<<(std::ostream& os, const icmp_header& header) + { return os.write(reinterpret_cast<const char*>(header.rep_), 8); } + +private: + unsigned short decode(int a, int b) const + { return (rep_[a] << 8) + rep_[b]; } + + void encode(int a, int b, unsigned short n) + { + rep_[a] = static_cast<unsigned char>(n >> 8); + rep_[b] = static_cast<unsigned char>(n & 0xFF); + } + + unsigned char rep_[8]; +}; + +template <typename Iterator> +void compute_checksum(icmp_header& header, + Iterator body_begin, Iterator body_end) +{ + unsigned int sum = (header.type() << 8) + header.code() + + header.identifier() + header.sequence_number(); + + Iterator body_iter = body_begin; + while (body_iter != body_end) + { + sum += (static_cast<unsigned char>(*body_iter++) << 8); + if (body_iter != body_end) + sum += static_cast<unsigned char>(*body_iter++); + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + header.checksum(static_cast<unsigned short>(~sum)); +} + +#endif // ICMP_HEADER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/icmp/ipv4_header.hpp b/3rdparty/asio/src/examples/cpp11/icmp/ipv4_header.hpp new file mode 100644 index 00000000000..d296571938f --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/icmp/ipv4_header.hpp @@ -0,0 +1,102 @@ +// +// ipv4_header.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 IPV4_HEADER_HPP +#define IPV4_HEADER_HPP + +#include <algorithm> +#include <asio/ip/address_v4.hpp> + +// Packet header for IPv4. +// +// The wire format of an IPv4 header is: +// +// 0 8 16 31 +// +-------+-------+---------------+------------------------------+ --- +// | | | | | ^ +// |version|header | type of | total length in bytes | | +// | (4) | length| service | | | +// +-------+-------+---------------+-+-+-+------------------------+ | +// | | | | | | | +// | identification |0|D|M| fragment offset | | +// | | |F|F| | | +// +---------------+---------------+-+-+-+------------------------+ | +// | | | | | +// | time to live | protocol | header checksum | 20 bytes +// | | | | | +// +---------------+---------------+------------------------------+ | +// | | | +// | source IPv4 address | | +// | | | +// +--------------------------------------------------------------+ | +// | | | +// | destination IPv4 address | | +// | | v +// +--------------------------------------------------------------+ --- +// | | ^ +// | | | +// / options (if any) / 0 - 40 +// / / bytes +// | | | +// | | v +// +--------------------------------------------------------------+ --- + +class ipv4_header +{ +public: + ipv4_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); } + + unsigned char version() const { return (rep_[0] >> 4) & 0xF; } + unsigned short header_length() const { return (rep_[0] & 0xF) * 4; } + unsigned char type_of_service() const { return rep_[1]; } + unsigned short total_length() const { return decode(2, 3); } + unsigned short identification() const { return decode(4, 5); } + bool dont_fragment() const { return (rep_[6] & 0x40) != 0; } + bool more_fragments() const { return (rep_[6] & 0x20) != 0; } + unsigned short fragment_offset() const { return decode(6, 7) & 0x1FFF; } + unsigned int time_to_live() const { return rep_[8]; } + unsigned char protocol() const { return rep_[9]; } + unsigned short header_checksum() const { return decode(10, 11); } + + asio::ip::address_v4 source_address() const + { + asio::ip::address_v4::bytes_type bytes + = { { rep_[12], rep_[13], rep_[14], rep_[15] } }; + return asio::ip::address_v4(bytes); + } + + asio::ip::address_v4 destination_address() const + { + asio::ip::address_v4::bytes_type bytes + = { { rep_[16], rep_[17], rep_[18], rep_[19] } }; + return asio::ip::address_v4(bytes); + } + + friend std::istream& operator>>(std::istream& is, ipv4_header& header) + { + is.read(reinterpret_cast<char*>(header.rep_), 20); + if (header.version() != 4) + is.setstate(std::ios::failbit); + std::streamsize options_length = header.header_length() - 20; + if (options_length < 0 || options_length > 40) + is.setstate(std::ios::failbit); + else + is.read(reinterpret_cast<char*>(header.rep_) + 20, options_length); + return is; + } + +private: + unsigned short decode(int a, int b) const + { return (rep_[a] << 8) + rep_[b]; } + + unsigned char rep_[60]; +}; + +#endif // IPV4_HEADER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/icmp/ping.cpp b/3rdparty/asio/src/examples/cpp11/icmp/ping.cpp new file mode 100644 index 00000000000..f179ea3461b --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/icmp/ping.cpp @@ -0,0 +1,162 @@ +// +// ping.cpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <istream> +#include <iostream> +#include <ostream> + +#include "icmp_header.hpp" +#include "ipv4_header.hpp" + +using asio::ip::icmp; +using asio::steady_timer; +namespace chrono = asio::chrono; + +class pinger +{ +public: + pinger(asio::io_context& io_context, const char* destination) + : resolver_(io_context), socket_(io_context, icmp::v4()), + timer_(io_context), sequence_number_(0), num_replies_(0) + { + destination_ = *resolver_.resolve(icmp::v4(), destination, "").begin(); + + start_send(); + start_receive(); + } + +private: + void start_send() + { + std::string body("\"Hello!\" from Asio ping."); + + // Create an ICMP header for an echo request. + icmp_header echo_request; + echo_request.type(icmp_header::echo_request); + echo_request.code(0); + echo_request.identifier(get_identifier()); + echo_request.sequence_number(++sequence_number_); + compute_checksum(echo_request, body.begin(), body.end()); + + // Encode the request packet. + asio::streambuf request_buffer; + std::ostream os(&request_buffer); + os << echo_request << body; + + // Send the request. + time_sent_ = steady_timer::clock_type::now(); + socket_.send_to(request_buffer.data(), destination_); + + // Wait up to five seconds for a reply. + num_replies_ = 0; + timer_.expires_at(time_sent_ + chrono::seconds(5)); + timer_.async_wait(std::bind(&pinger::handle_timeout, this)); + } + + void handle_timeout() + { + if (num_replies_ == 0) + std::cout << "Request timed out" << std::endl; + + // Requests must be sent no less than one second apart. + timer_.expires_at(time_sent_ + chrono::seconds(1)); + timer_.async_wait(std::bind(&pinger::start_send, this)); + } + + void start_receive() + { + // Discard any data already in the buffer. + reply_buffer_.consume(reply_buffer_.size()); + + // Wait for a reply. We prepare the buffer to receive up to 64KB. + socket_.async_receive(reply_buffer_.prepare(65536), + std::bind(&pinger::handle_receive, this, std::placeholders::_2)); + } + + void handle_receive(std::size_t length) + { + // The actual number of bytes received is committed to the buffer so that we + // can extract it using a std::istream object. + reply_buffer_.commit(length); + + // Decode the reply packet. + std::istream is(&reply_buffer_); + ipv4_header ipv4_hdr; + icmp_header icmp_hdr; + is >> ipv4_hdr >> icmp_hdr; + + // We can receive all ICMP packets received by the host, so we need to + // filter out only the echo replies that match the our identifier and + // expected sequence number. + if (is && icmp_hdr.type() == icmp_header::echo_reply + && icmp_hdr.identifier() == get_identifier() + && icmp_hdr.sequence_number() == sequence_number_) + { + // If this is the first reply, interrupt the five second timeout. + if (num_replies_++ == 0) + timer_.cancel(); + + // Print out some information about the reply packet. + chrono::steady_clock::time_point now = chrono::steady_clock::now(); + chrono::steady_clock::duration elapsed = now - time_sent_; + std::cout << length - ipv4_hdr.header_length() + << " bytes from " << ipv4_hdr.source_address() + << ": icmp_seq=" << icmp_hdr.sequence_number() + << ", ttl=" << ipv4_hdr.time_to_live() + << ", time=" + << chrono::duration_cast<chrono::milliseconds>(elapsed).count() + << std::endl; + } + + start_receive(); + } + + static unsigned short get_identifier() + { +#if defined(ASIO_WINDOWS) + return static_cast<unsigned short>(::GetCurrentProcessId()); +#else + return static_cast<unsigned short>(::getpid()); +#endif + } + + icmp::resolver resolver_; + icmp::endpoint destination_; + icmp::socket socket_; + steady_timer timer_; + unsigned short sequence_number_; + chrono::steady_clock::time_point time_sent_; + asio::streambuf reply_buffer_; + std::size_t num_replies_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: ping <host>" << std::endl; +#if !defined(ASIO_WINDOWS) + std::cerr << "(You may need to run this program as root.)" << std::endl; +#endif + return 1; + } + + asio::io_context io_context; + pinger p(io_context, argv[1]); + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << std::endl; + } +} diff --git a/3rdparty/asio/src/examples/cpp11/invocation/prioritised_handlers.cpp b/3rdparty/asio/src/examples/cpp11/invocation/prioritised_handlers.cpp index 8435d6e46d6..533bfd06861 100644 --- a/3rdparty/asio/src/examples/cpp11/invocation/prioritised_handlers.cpp +++ b/3rdparty/asio/src/examples/cpp11/invocation/prioritised_handlers.cpp @@ -2,7 +2,7 @@ // prioritised_handlers.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -142,13 +142,13 @@ private: //---------------------------------------------------------------------- -void high_priority_handler(const asio::error_code& /*ec*/, +void high_priority_handler(const std::error_code& /*ec*/, tcp::socket /*socket*/) { std::cout << "High priority handler\n"; } -void middle_priority_handler(const asio::error_code& /*ec*/) +void middle_priority_handler(const std::error_code& /*ec*/) { std::cout << "Middle priority handler\n"; } diff --git a/3rdparty/asio/src/examples/cpp11/iostreams/daytime_client.cpp b/3rdparty/asio/src/examples/cpp11/iostreams/daytime_client.cpp new file mode 100644 index 00000000000..0c8df192534 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/iostreams/daytime_client.cpp @@ -0,0 +1,44 @@ +// +// daytime_client.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include <string> +#include <asio.hpp> + +using asio::ip::tcp; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: daytime_client <host>" << std::endl; + return 1; + } + + tcp::iostream s(argv[1], "daytime"); + if (!s) + { + std::cout << "Unable to connect: " << s.error().message() << std::endl; + return 1; + } + + std::string line; + std::getline(s, line); + std::cout << line << std::endl; + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/iostreams/daytime_server.cpp b/3rdparty/asio/src/examples/cpp11/iostreams/daytime_server.cpp new file mode 100644 index 00000000000..1e644085ef1 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/iostreams/daytime_server.cpp @@ -0,0 +1,51 @@ +// +// daytime_server.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <ctime> +#include <iostream> +#include <string> +#include <asio.hpp> + +using asio::ip::tcp; + +std::string make_daytime_string() +{ + using namespace std; // For time_t, time and ctime; + time_t now = time(0); + return ctime(&now); +} + +int main() +{ + try + { + asio::io_context io_context; + + tcp::endpoint endpoint(tcp::v4(), 13); + tcp::acceptor acceptor(io_context, endpoint); + + for (;;) + { + tcp::iostream stream; + std::error_code ec; + acceptor.accept(stream.socket(), ec); + if (!ec) + { + stream << make_daytime_string(); + } + } + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/iostreams/http_client.cpp b/3rdparty/asio/src/examples/cpp11/iostreams/http_client.cpp index cd46733a397..313f177bce4 100644 --- a/3rdparty/asio/src/examples/cpp11/iostreams/http_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/iostreams/http_client.cpp @@ -2,7 +2,7 @@ // http_client.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/local/connect_pair.cpp b/3rdparty/asio/src/examples/cpp11/local/connect_pair.cpp index 2571ff93360..50d0a06712c 100644 --- a/3rdparty/asio/src/examples/cpp11/local/connect_pair.cpp +++ b/3rdparty/asio/src/examples/cpp11/local/connect_pair.cpp @@ -2,7 +2,7 @@ // connect_pair.cpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -44,7 +44,7 @@ private: } else { - throw asio::system_error(ec); + throw std::system_error(ec); } }); } @@ -61,7 +61,7 @@ private: } else { - throw asio::system_error(ec); + throw std::system_error(ec); } }); } diff --git a/3rdparty/asio/src/examples/cpp11/local/fd_passing_stream_client.cpp b/3rdparty/asio/src/examples/cpp11/local/fd_passing_stream_client.cpp new file mode 100644 index 00000000000..229509f1c14 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/local/fd_passing_stream_client.cpp @@ -0,0 +1,102 @@ +// +// fd_passing_stream_client.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2021 Heiko Hund (heiko at openvpn dot net) +// +// 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) +// + +// Demonstrates how to pass file descriptors between processes with Asio. +// The client send a file name (destfile) to the server. The server opens +// the file and the associated file descriptor back to the client. + +#include <cstdlib> +#include <cstring> +#include <iostream> +#include "asio.hpp" + +#if defined(ASIO_HAS_LOCAL_SOCKETS) + +#include <sys/types.h> +#include <sys/socket.h> + +using asio::local::stream_protocol; + +constexpr std::size_t max_length = 1024; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: fd_passing_stream_client <serversocket>\n"; + return 1; + } + + asio::io_context io_context; + + stream_protocol::socket s(io_context); + s.connect(stream_protocol::endpoint(argv[1])); + + std::cout << "Enter path to write to: "; + char request[max_length]; + std::cin.getline(request, max_length); + size_t request_length = std::strlen(request); + asio::write(s, asio::buffer(request, request_length)); + + char reply[max_length]; + struct msghdr msg = {}; + struct iovec iov = { reply, sizeof(reply) }; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + union + { + struct cmsghdr align; + char buf[CMSG_SPACE(sizeof(int))]; + } cmsgu; + msg.msg_control = cmsgu.buf; + msg.msg_controllen = sizeof(cmsgu.buf); + + ::recvmsg(s.native_handle(), &msg, 0); + + int fd = -1; + struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); + while (cmsg != NULL) + { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) + { + std::memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + break; + } + cmsg = CMSG_NXTHDR(&msg, cmsg); + } + + if (fd != -1) + { + std::cout << "File descriptor received is: " << fd << "\n"; + FILE* f(::fdopen(fd, "w+")); + if (f) + { + ::fprintf(f, "stream_client writing to received fd #%d\n", fd); + ::fclose(f); + } + else + ::close(fd); + } + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} + +#else // defined(ASIO_HAS_LOCAL_SOCKETS) +# error Local sockets not available on this platform. +#endif // defined(ASIO_HAS_LOCAL_SOCKETS) diff --git a/3rdparty/asio/src/examples/cpp11/local/fd_passing_stream_server.cpp b/3rdparty/asio/src/examples/cpp11/local/fd_passing_stream_server.cpp new file mode 100644 index 00000000000..5082185e75c --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/local/fd_passing_stream_server.cpp @@ -0,0 +1,160 @@ +// +// fd_passing_stream_server.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2021 Heiko Hund (heiko at openvpn dot net) +// +// 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) +// + +// Demonstrates how to pass file descriptors between processes with Asio. +// The client sends a file name to the server. The server opens the file and +// passes the associated file descriptor back to the client. + +#include <array> +#include <cstdio> +#include <cassert> +#include <iostream> +#include <memory> +#include "asio.hpp" + +#if defined(ASIO_HAS_LOCAL_SOCKETS) + +using asio::local::stream_protocol; + +class session + : public std::enable_shared_from_this<session> +{ +public: + session(stream_protocol::socket sock) + : socket_(std::move(sock)) + { + } + + void start() + { + do_read(); + } + +private: + void do_read() + { + auto self(shared_from_this()); + socket_.async_read_some(asio::buffer(data_), + [this, self](std::error_code ec, std::size_t length) + { + if (ec) + return; + + assert(length < data_.size()); + data_[length] = 0; + do_write(data_.data()); + }); + } + + void do_write(const char* filename) + { + auto self(shared_from_this()); + socket_.async_wait(stream_protocol::socket::wait_write, + [this, self, filename](std::error_code ec) + { + if (ec) + return; + + FILE* f(::fopen(filename, "w+")); + if (!f) + return; + + struct msghdr msg = {}; + char buf[] = { 0 }; + struct iovec iov = { buf, sizeof(buf) }; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + union + { + struct cmsghdr align; + char buf[CMSG_SPACE(sizeof(int))]; + } cmsgu; + msg.msg_control = cmsgu.buf; + msg.msg_controllen = sizeof(cmsgu.buf); + + struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + int fd = ::fileno(f); + std::memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + + ssize_t s(::sendmsg(socket_.native_handle(), &msg, 0)); + ::fclose(f); + if (s != -1) + do_read(); + }); + } + + // The socket used to communicate with the client. + stream_protocol::socket socket_; + + // Buffer used to store data received from the client. + std::array<char, 1024> data_; +}; + +class server +{ +public: + server(asio::io_context& io_context, const std::string& file) + : acceptor_(io_context, stream_protocol::endpoint(file)) + { + do_accept(); + } + +private: + void do_accept() + { + acceptor_.async_accept( + [this](std::error_code ec, stream_protocol::socket socket) + { + if (!ec) + { + std::make_shared<session>(std::move(socket))->start(); + } + + do_accept(); + }); + } + + stream_protocol::acceptor acceptor_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: fd_passing_stream_server <socketfile>\n"; + std::cerr << "*** WARNING: existing file is removed ***\n"; + return 1; + } + + asio::io_context io_context; + + std::remove(argv[1]); + server s(io_context, argv[1]); + + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} + +#else // defined(ASIO_HAS_LOCAL_SOCKETS) +# error Local sockets not available on this platform. +#endif // defined(ASIO_HAS_LOCAL_SOCKETS) diff --git a/3rdparty/asio/src/examples/cpp11/local/iostream_client.cpp b/3rdparty/asio/src/examples/cpp11/local/iostream_client.cpp index c7549278124..932f29d3459 100644 --- a/3rdparty/asio/src/examples/cpp11/local/iostream_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/local/iostream_client.cpp @@ -2,7 +2,7 @@ // stream_client.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/local/stream_client.cpp b/3rdparty/asio/src/examples/cpp11/local/stream_client.cpp index 19806c92510..32f408933ca 100644 --- a/3rdparty/asio/src/examples/cpp11/local/stream_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/local/stream_client.cpp @@ -2,7 +2,7 @@ // stream_client.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/local/stream_server.cpp b/3rdparty/asio/src/examples/cpp11/local/stream_server.cpp index 6b590fbfbf9..85cd58f87d6 100644 --- a/3rdparty/asio/src/examples/cpp11/local/stream_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/local/stream_server.cpp @@ -2,7 +2,7 @@ // stream_server.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/multicast/receiver.cpp b/3rdparty/asio/src/examples/cpp11/multicast/receiver.cpp index 9cb032c4148..5973bede5bb 100644 --- a/3rdparty/asio/src/examples/cpp11/multicast/receiver.cpp +++ b/3rdparty/asio/src/examples/cpp11/multicast/receiver.cpp @@ -2,7 +2,7 @@ // receiver.cpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/multicast/sender.cpp b/3rdparty/asio/src/examples/cpp11/multicast/sender.cpp index cb70d46ccd4..dc3cf7fd0e7 100644 --- a/3rdparty/asio/src/examples/cpp11/multicast/sender.cpp +++ b/3rdparty/asio/src/examples/cpp11/multicast/sender.cpp @@ -2,7 +2,7 @@ // sender.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/nonblocking/third_party_lib.cpp b/3rdparty/asio/src/examples/cpp11/nonblocking/third_party_lib.cpp index 5ce61536198..7239a598532 100644 --- a/3rdparty/asio/src/examples/cpp11/nonblocking/third_party_lib.cpp +++ b/3rdparty/asio/src/examples/cpp11/nonblocking/third_party_lib.cpp @@ -2,7 +2,7 @@ // third_party_lib.cpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_1.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_1.cpp index cfec43c8e83..054dbdbbc88 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_1.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_1.cpp @@ -2,12 +2,13 @@ // composed_1.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // +#include <asio/deferred.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/use_future.hpp> @@ -31,14 +32,25 @@ template <typename CompletionToken> auto async_write_message(tcp::socket& socket, const char* message, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is void. However, - // when the completion token is asio::yield_context (used for stackful - // coroutines) the return type would be std::size_t, and when the completion - // token is asio::use_future it would be std::future<std::size_t>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code, std::size_t)>::return_type + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is void. + // However, when the completion token is asio::yield_context (used for + // stackful coroutines) the return type would be std::size_t, and when the + // completion token is asio::use_future it would be std::future<std::size_t>. + // When the completion token is asio::deferred, the return type differs for + // each asynchronous operation. + // + // In this example we are trivially delegating to an underlying asynchronous + // operation, so we can deduce the return type from that. + -> decltype( + asio::async_write(socket, + asio::buffer(message, std::strlen(message)), + std::forward<CompletionToken>(token))) { // When delegating to the underlying operation we must take care to perfectly // forward the completion token. This ensures that our operation works @@ -77,6 +89,39 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + "Testing deferred\r\n", asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error, std::size_t n) + { + if (!error) + { + std::cout << n << " bytes transferred\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -109,5 +154,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_2.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_2.cpp index 62ddf8d9089..306d4b343b4 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_2.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_2.cpp @@ -2,12 +2,13 @@ // composed_2.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // +#include <asio/deferred.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/use_future.hpp> @@ -20,6 +21,10 @@ using asio::ip::tcp; +// NOTE: This example requires the new asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + //------------------------------------------------------------------------------ // This next simplest example of a composed asynchronous operation involves @@ -28,43 +33,102 @@ using asio::ip::tcp; // asynchronous operation requirements are met by delegating responsibility to // the underlying operations. +// In addition to determining the mechanism by which an asynchronous operation +// delivers its result, a completion token also determines the time when the +// operation commences. For example, when the completion token is a simple +// callback the operation commences before the initiating function returns. +// However, if the completion token's delivery mechanism uses a future, we +// might instead want to defer initiation of the operation until the returned +// future object is waited upon. +// +// To enable this, when implementing an asynchronous operation we must package +// the initiation step as a function object. +struct async_write_message_initiation +{ + // The initiation function object's call operator is passed the concrete + // completion handler produced by the completion token. This completion + // handler matches the asynchronous operation's completion handler signature, + // which in this example is: + // + // void(std::error_code error, std::size_t) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments as members in the initiaton function object. However, we should + // prefer to propagate them as function call arguments as this allows the + // completion token to optimise how they are passed. For example, a lazy + // future which defers initiation would need to make a decay-copy of the + // arguments, but when using a simple callback the arguments can be trivially + // forwarded straight through.) + template <typename CompletionHandler> + void operator()(CompletionHandler&& completion_handler, tcp::socket& socket, + const char* message, bool allow_partial_write) const + { + if (allow_partial_write) + { + // When delegating to an underlying operation we must take care to + // perfectly forward the completion handler. This ensures that our + // operation works correctly with move-only function objects as + // callbacks. + return socket.async_write_some( + asio::buffer(message, std::strlen(message)), + std::forward<CompletionHandler>(completion_handler)); + } + else + { + // As above, we must perfectly forward the completion handler when calling + // the alternate underlying operation. + return asio::async_write(socket, + asio::buffer(message, std::strlen(message)), + std::forward<CompletionHandler>(completion_handler)); + } + } +}; + template <typename CompletionToken> auto async_write_message(tcp::socket& socket, const char* message, bool allow_partial_write, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is void. However, - // when the completion token is asio::yield_context (used for stackful - // coroutines) the return type would be std::size_t, and when the completion - // token is asio::use_future it would be std::future<std::size_t>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code, std::size_t)>::return_type + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is void. + // However, when the completion token is asio::yield_context (used for + // stackful coroutines) the return type would be std::size_t, and when the + // completion token is asio::use_future it would be std::future<std::size_t>. + // When the completion token is asio::deferred, the return type differs for + // each asynchronous operation. + // + // In C++11 we deduce the type from the call to asio::async_initiate. + -> decltype( + asio::async_initiate< + CompletionToken, void(std::error_code, std::size_t)>( + async_write_message_initiation(), + token, std::ref(socket), message, allow_partial_write)) { - // As the return type of the initiating function is deduced solely from the - // CompletionToken and completion signature, we know that two different - // asynchronous operations having the same completion signature will produce - // the same return type, when passed the same CompletionToken. This allows us - // to trivially delegate to alternate implementations. - if (allow_partial_write) - { - // When delegating to an underlying operation we must take care to - // perfectly forward the completion token. This ensures that our operation - // works correctly with move-only function objects as callbacks, as well as - // other completion token types. - return socket.async_write_some( - asio::buffer(message, std::strlen(message)), - std::forward<CompletionToken>(token)); - } - else - { - // As above, we must perfectly forward the completion token when calling - // the alternate underlying operation. - return asio::async_write(socket, - asio::buffer(message, std::strlen(message)), - std::forward<CompletionToken>(token)); - } + // The asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return asio::async_initiate< + CompletionToken, void(std::error_code, std::size_t)>( + async_write_message_initiation(), + token, std::ref(socket), message, allow_partial_write); } //------------------------------------------------------------------------------ @@ -95,6 +159,39 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + "Testing deferred\r\n", false, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error, std::size_t n) + { + if (!error) + { + std::cout << n << " bytes transferred\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -127,5 +224,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_3.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_3.cpp index c821041336f..e0b5ddca85b 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_3.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_3.cpp @@ -2,13 +2,14 @@ // composed_3.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // #include <asio/bind_executor.hpp> +#include <asio/deferred.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/use_future.hpp> @@ -96,15 +97,26 @@ template <typename CompletionToken> auto async_write_message(tcp::socket& socket, const char* message, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is always void. - // In this example, when the completion token is asio::yield_context - // (used for stackful coroutines) the return type would be also be void, as + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as // there is no non-error argument to the completion handler. When the - // completion token is asio::use_future it would be std::future<void>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code)>::return_type + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++11 we deduce the type from the call to asio::async_initiate. + -> decltype( + asio::async_initiate< + CompletionToken, void(std::error_code)>( + async_write_message_initiation(), + token, std::ref(socket), message)) { // The asio::async_initiate function takes: // @@ -155,6 +167,39 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + "Testing deferred\r\n", asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -188,5 +233,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_4.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_4.cpp index e4c6264b625..29fe26966e5 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_4.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_4.cpp @@ -2,13 +2,14 @@ // composed_4.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // #include <asio/bind_executor.hpp> +#include <asio/deferred.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/use_future.hpp> @@ -112,15 +113,26 @@ template <typename CompletionToken> auto async_write_message(tcp::socket& socket, const char* message, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is always void. - // In this example, when the completion token is asio::yield_context - // (used for stackful coroutines) the return type would be also be void, as + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as // there is no non-error argument to the completion handler. When the - // completion token is asio::use_future it would be std::future<void>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code)>::return_type + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++11 we deduce the type from the call to asio::async_initiate. + -> decltype( + asio::async_initiate< + CompletionToken, void(std::error_code)>( + async_write_message_initiation(), + token, std::ref(socket), message)) { // The asio::async_initiate function takes: // @@ -171,6 +183,38 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, "", asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -203,5 +247,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_5.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_5.cpp index 9f7901da512..06a7af40f41 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_5.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_5.cpp @@ -2,12 +2,13 @@ // composed_5.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // +#include <asio/deferred.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/use_future.hpp> @@ -142,15 +143,26 @@ template <typename T, typename CompletionToken> auto async_write_message(tcp::socket& socket, const T& message, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is always void. - // In this example, when the completion token is asio::yield_context - // (used for stackful coroutines) the return type would be also be void, as + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as // there is no non-error argument to the completion handler. When the - // completion token is asio::use_future it would be std::future<void>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code)>::return_type + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++11 we deduce the type from the call to asio::async_initiate. + -> decltype( + asio::async_initiate< + CompletionToken, void(std::error_code)>( + async_write_message_initiation(), token, + std::ref(socket), std::declval<std::unique_ptr<std::string>>())) { // Encode the message and copy it into an allocated buffer. The buffer will // be maintained for the lifetime of the asynchronous operation. @@ -207,6 +219,39 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + std::string("abcdef"), asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -239,5 +284,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_6.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_6.cpp index b55a553d07a..b948758d83a 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_6.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_6.cpp @@ -2,12 +2,13 @@ // composed_6.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // +#include <asio/deferred.hpp> #include <asio/executor_work_guard.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> @@ -97,9 +98,7 @@ struct async_write_message_initiation // As our composed operation performs multiple underlying I/O operations, // we should maintain a work object against the I/O executor. This tells // the I/O executor that there is still more work to come in the future. - typename std::decay<decltype(asio::prefer( - std::declval<tcp::socket::executor_type>(), - asio::execution::outstanding_work.tracked))>::type io_work_; + asio::executor_work_guard<tcp::socket::executor_type> io_work_; // The user-supplied completion handler, called once only on completion // of the entire composed operation. @@ -136,6 +135,9 @@ struct async_write_message_initiation // This point is reached only on completion of the entire composed // operation. + // We no longer have any future work coming for the I/O executor. + io_work_.reset(); + // Deallocate the encoded message before calling the user-supplied // completion handler. encoded_message_.reset(); @@ -186,8 +188,7 @@ struct async_write_message_initiation socket, std::move(encoded_message), repeat_count, std::move(delay_timer), intermediate_completion_handler::starting, - asio::prefer(socket.get_executor(), - asio::execution::outstanding_work.tracked), + asio::make_work_guard(socket.get_executor()), std::forward<CompletionHandler>(completion_handler)}); } }; @@ -197,15 +198,27 @@ auto async_write_messages(tcp::socket& socket, const T& message, std::size_t repeat_count, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is always void. - // In this example, when the completion token is asio::yield_context - // (used for stackful coroutines) the return type would be also be void, as + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as // there is no non-error argument to the completion handler. When the - // completion token is asio::use_future it would be std::future<void>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code)>::return_type + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++11 we deduce the type from the call to asio::async_initiate. + -> decltype( + asio::async_initiate< + CompletionToken, void(std::error_code)>( + async_write_message_initiation(), token, std::ref(socket), + std::declval<std::unique_ptr<std::string>>(), repeat_count, + std::declval<std::unique_ptr<asio::steady_timer>>())) { // Encode the message and copy it into an allocated buffer. The buffer will // be maintained for the lifetime of the composed asynchronous operation. @@ -266,6 +279,39 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_messages(socket, + "Testing deferred\r\n", 5, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -298,5 +344,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_7.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_7.cpp index 92c8e321c01..8eb83dc7679 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_7.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_7.cpp @@ -2,13 +2,14 @@ // composed_7.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // #include <asio/compose.hpp> +#include <asio/deferred.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/steady_timer.hpp> @@ -118,15 +119,26 @@ auto async_write_messages(tcp::socket& socket, const T& message, std::size_t repeat_count, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is always void. - // In this example, when the completion token is asio::yield_context - // (used for stackful coroutines) the return type would be also be void, as + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as // there is no non-error argument to the completion handler. When the - // completion token is asio::use_future it would be std::future<void>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code)>::return_type + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++11 we deduce the type from the call to asio::async_compose. + -> decltype( + asio::async_compose< + CompletionToken, void(std::error_code)>( + std::declval<async_write_messages_implementation>(), + token, socket)) { // Encode the message and copy it into an allocated buffer. The buffer will // be maintained for the lifetime of the composed asynchronous operation. @@ -186,6 +198,39 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_messages(socket, + "Testing deferred\r\n", 5, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -218,5 +263,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/operations/composed_8.cpp b/3rdparty/asio/src/examples/cpp11/operations/composed_8.cpp index 7c24c7251c6..ce22a5b418d 100644 --- a/3rdparty/asio/src/examples/cpp11/operations/composed_8.cpp +++ b/3rdparty/asio/src/examples/cpp11/operations/composed_8.cpp @@ -2,13 +2,14 @@ // composed_8.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // #include <asio/compose.hpp> +#include <asio/deferred.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/steady_timer.hpp> @@ -114,15 +115,26 @@ auto async_write_messages(tcp::socket& socket, const T& message, std::size_t repeat_count, CompletionToken&& token) // The return type of the initiating function is deduced from the combination - // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is always void. - // In this example, when the completion token is asio::yield_context - // (used for stackful coroutines) the return type would be also be void, as + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as // there is no non-error argument to the completion handler. When the - // completion token is asio::use_future it would be std::future<void>. - -> typename asio::async_result< - typename std::decay<CompletionToken>::type, - void(std::error_code)>::return_type + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++11 we deduce the type from the call to asio::async_compose. + -> decltype( + asio::async_compose< + CompletionToken, void(std::error_code)>( + std::declval<async_write_messages_implementation>(), + token, socket)) { // Encode the message and copy it into an allocated buffer. The buffer will // be maintained for the lifetime of the composed asynchronous operation. @@ -181,6 +193,39 @@ void test_callback() //------------------------------------------------------------------------------ +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation and its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_messages(socket, + "Testing deferred\r\n", 5, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + void test_future() { asio::io_context io_context; @@ -213,5 +258,6 @@ void test_future() int main() { test_callback(); + test_deferred(); test_future(); } diff --git a/3rdparty/asio/src/examples/cpp11/parallel_group/ranged_wait_for_all.cpp b/3rdparty/asio/src/examples/cpp11/parallel_group/ranged_wait_for_all.cpp new file mode 100644 index 00000000000..18772884072 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/parallel_group/ranged_wait_for_all.cpp @@ -0,0 +1,70 @@ +// +// ranged_wait_for_all.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> +#include <vector> + +#ifdef ASIO_HAS_POSIX_STREAM_DESCRIPTOR + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor out(ctx, ::dup(STDOUT_FILENO)); + asio::posix::stream_descriptor err(ctx, ::dup(STDERR_FILENO)); + + using op_type = decltype( + out.async_write_some( + asio::buffer("", 0), + asio::deferred + ) + ); + + std::vector<op_type> ops; + + ops.push_back( + out.async_write_some( + asio::buffer("first\r\n", 7), + asio::deferred + ) + ); + + ops.push_back( + err.async_write_some( + asio::buffer("second\r\n", 8), + asio::deferred + ) + ); + + asio::experimental::make_parallel_group(ops).async_wait( + asio::experimental::wait_for_all(), + []( + std::vector<std::size_t> completion_order, + std::vector<std::error_code> ec, + std::vector<std::size_t> n + ) + { + for (std::size_t i = 0; i < completion_order.size(); ++i) + { + std::size_t idx = completion_order[i]; + std::cout << "operation " << idx << " finished: "; + std::cout << ec[idx] << ", " << n[idx] << "\n"; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_all.cpp b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_all.cpp new file mode 100644 index 00000000000..a489a2966da --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_all.cpp @@ -0,0 +1,62 @@ +// +// wait_for_all.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <asio/experimental/deferred.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#ifdef ASIO_HAS_POSIX_STREAM_DESCRIPTOR + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + in.async_read_some( + asio::buffer(data), + asio::deferred), + timer.async_wait( + asio::deferred) + ).async_wait( + asio::experimental::wait_for_all(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one.cpp b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one.cpp new file mode 100644 index 00000000000..499684af69f --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one.cpp @@ -0,0 +1,62 @@ +// +// wait_for_one.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <asio/experimental/deferred.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + in.async_read_some( + asio::buffer(data), + asio::deferred), + timer.async_wait( + asio::deferred) + ).async_wait( + asio::experimental::wait_for_one(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one_error.cpp b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one_error.cpp new file mode 100644 index 00000000000..f6e52d6ca0e --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one_error.cpp @@ -0,0 +1,62 @@ +// +// wait_for_one_error.cpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <asio/experimental/deferred.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + in.async_read_some( + asio::buffer(data), + asio::deferred), + timer.async_wait( + asio::deferred) + ).async_wait( + asio::experimental::wait_for_one_error(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one_success.cpp b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one_success.cpp new file mode 100644 index 00000000000..16fd2130ab8 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/parallel_group/wait_for_one_success.cpp @@ -0,0 +1,62 @@ +// +// wait_for_one_error.cpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <asio/experimental/deferred.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + in.async_read_some( + asio::buffer(data), + asio::deferred), + timer.async_wait( + asio::deferred) + ).async_wait( + asio::experimental::wait_for_one_success(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp11/porthopper/client.cpp b/3rdparty/asio/src/examples/cpp11/porthopper/client.cpp new file mode 100644 index 00000000000..e0936128d72 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/porthopper/client.cpp @@ -0,0 +1,188 @@ +// +// client.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <algorithm> +#include <cstdlib> +#include <exception> +#include <iostream> +#include <memory> +#include <string> +#include <utility> +#include "protocol.hpp" + +using asio::ip::tcp; +using asio::ip::udp; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cerr << "Usage: client <host> <port>\n"; + return 1; + } + using namespace std; // For atoi. + std::string host_name = argv[1]; + std::string port = argv[2]; + + asio::io_context io_context; + + // Determine the location of the server. + tcp::resolver resolver(io_context); + tcp::endpoint remote_endpoint = *resolver.resolve(host_name, port).begin(); + + // Establish the control connection to the server. + tcp::socket control_socket(io_context); + control_socket.connect(remote_endpoint); + + // Create a datagram socket to receive data from the server. + udp::socket data_socket(io_context, udp::endpoint(udp::v4(), 0)); + + // Determine what port we will receive data on. + udp::endpoint data_endpoint = data_socket.local_endpoint(); + + // Ask the server to start sending us data. + control_request start = control_request::start(data_endpoint.port()); + asio::write(control_socket, start.to_buffers()); + + unsigned long last_frame_number = 0; + for (;;) + { + // Receive 50 messages on the current data socket. + for (int i = 0; i < 50; ++i) + { + // Receive a frame from the server. + frame f; + data_socket.receive(f.to_buffers(), 0); + if (f.number() > last_frame_number) + { + last_frame_number = f.number(); + std::cout << "\n" << f.payload(); + } + } + + // Time to switch to a new socket. To ensure seamless handover we will + // continue to receive packets using the old socket until data arrives on + // the new one. + std::cout << " Starting renegotiation"; + + // Create the new data socket. + udp::socket new_data_socket(io_context, udp::endpoint(udp::v4(), 0)); + + // Determine the new port we will use to receive data. + udp::endpoint new_data_endpoint = new_data_socket.local_endpoint(); + + // Ask the server to switch over to the new port. + control_request change = control_request::change( + data_endpoint.port(), new_data_endpoint.port()); + std::error_code control_result; + asio::async_write(control_socket, change.to_buffers(), + [&](std::error_code ec, std::size_t /*length*/) + { + control_result = ec; + }); + + // Try to receive a frame from the server on the new data socket. If we + // successfully receive a frame on this new data socket we can consider + // the renegotation complete. In that case we will close the old data + // socket, which will cause any outstanding receive operation on it to be + // cancelled. + frame f1; + std::error_code new_data_socket_result; + new_data_socket.async_receive(f1.to_buffers(), + [&](std::error_code ec, std::size_t /*length*/) + { + new_data_socket_result = ec; + if (!ec) + { + // We have successfully received a frame on the new data socket, + // so we can close the old data socket. This will cancel any + // outstanding receive operation on the old data socket. + data_socket.close(); + } + }); + + // This loop will continue until we have successfully completed the + // renegotiation (i.e. received a frame on the new data socket), or some + // unrecoverable error occurs. + bool done = false; + while (!done) + { + // Even though we're performing a renegotation, we want to continue + // receiving data as smoothly as possible. Therefore we will continue to + // try to receive a frame from the server on the old data socket. If we + // receive a frame on this socket we will interrupt the io_context, + // print the frame, and resume waiting for the other operations to + // complete. + frame f2; + done = true; // Let's be optimistic. + if (data_socket.is_open()) // May have been closed by receive handler. + { + data_socket.async_receive(f2.to_buffers(), 0, + [&](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + // We have successfully received a frame on the old data + // socket. Stop the io_context so that we can print it. + io_context.stop(); + done = false; + } + }); + } + + // Run the operations in parallel. This will block until all operations + // have finished, or until the io_context is interrupted. (No threads!) + io_context.restart(); + io_context.run(); + + // If the io_context.run() was interrupted then we have received a frame + // on the old data socket. We need to keep waiting for the renegotation + // operations to complete. + if (!done) + { + if (f2.number() > last_frame_number) + { + last_frame_number = f2.number(); + std::cout << "\n" << f2.payload(); + } + } + } + + // Since the loop has finished, we have either successfully completed + // the renegotation, or an error has occurred. First we'll check for + // errors. + if (control_result) + throw std::system_error(control_result); + if (new_data_socket_result) + throw std::system_error(new_data_socket_result); + + // If we get here it means we have successfully started receiving data on + // the new data socket. This new data socket will be used from now on + // (until the next time we renegotiate). + std::cout << " Renegotiation complete"; + data_socket = std::move(new_data_socket); + data_endpoint = new_data_endpoint; + if (f1.number() > last_frame_number) + { + last_frame_number = f1.number(); + std::cout << "\n" << f1.payload(); + } + } + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/porthopper/protocol.hpp b/3rdparty/asio/src/examples/cpp11/porthopper/protocol.hpp new file mode 100644 index 00000000000..46f9938cad5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/porthopper/protocol.hpp @@ -0,0 +1,156 @@ +// +// protocol.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 PORTHOPPER_PROTOCOL_HPP +#define PORTHOPPER_PROTOCOL_HPP + +#include <asio.hpp> +#include <array> +#include <cstring> +#include <iomanip> +#include <string> +#include <strstream> + +// This request is sent by the client to the server over a TCP connection. +// The client uses it to perform three functions: +// - To request that data start being sent to a given port. +// - To request that data is no longer sent to a given port. +// - To change the target port to another. +class control_request +{ +public: + // Construct an empty request. Used when receiving. + control_request() + { + } + + // Create a request to start sending data to a given port. + static const control_request start(unsigned short port) + { + return control_request(0, port); + } + + // Create a request to stop sending data to a given port. + static const control_request stop(unsigned short port) + { + return control_request(port, 0); + } + + // Create a request to change the port that data is sent to. + static const control_request change( + unsigned short old_port, unsigned short new_port) + { + return control_request(old_port, new_port); + } + + // Get the old port. Returns 0 for start requests. + unsigned short old_port() const + { + std::istrstream is(data_, encoded_port_size); + unsigned short port = 0; + is >> std::setw(encoded_port_size) >> std::hex >> port; + return port; + } + + // Get the new port. Returns 0 for stop requests. + unsigned short new_port() const + { + std::istrstream is(data_ + encoded_port_size, encoded_port_size); + unsigned short port = 0; + is >> std::setw(encoded_port_size) >> std::hex >> port; + return port; + } + + // Obtain buffers for reading from or writing to a socket. + std::array<asio::mutable_buffer, 1> to_buffers() + { + std::array<asio::mutable_buffer, 1> buffers + = { { asio::buffer(data_) } }; + return buffers; + } + +private: + // Construct with specified old and new ports. + control_request(unsigned short old_port_number, + unsigned short new_port_number) + { + std::ostrstream os(data_, control_request_size); + os << std::setw(encoded_port_size) << std::hex << old_port_number; + os << std::setw(encoded_port_size) << std::hex << new_port_number; + } + + // The length in bytes of a control_request and its components. + enum + { + encoded_port_size = 4, // 16-bit port in hex. + control_request_size = encoded_port_size * 2 + }; + + // The encoded request data. + char data_[control_request_size]; +}; + +// This frame is sent from the server to subscribed clients over UDP. +class frame +{ +public: + // The maximum allowable length of the payload. + enum { payload_size = 32 }; + + // Construct an empty frame. Used when receiving. + frame() + { + } + + // Construct a frame with specified frame number and payload. + frame(unsigned long frame_number, const std::string& payload_data) + { + std::ostrstream os(data_, frame_size); + os << std::setw(encoded_number_size) << std::hex << frame_number; + os << std::setw(payload_size) + << std::setfill(' ') << payload_data.substr(0, payload_size); + } + + // Get the frame number. + unsigned long number() const + { + std::istrstream is(data_, encoded_number_size); + unsigned long frame_number = 0; + is >> std::setw(encoded_number_size) >> std::hex >> frame_number; + return frame_number; + } + + // Get the payload data. + const std::string payload() const + { + return std::string(data_ + encoded_number_size, payload_size); + } + + // Obtain buffers for reading from or writing to a socket. + std::array<asio::mutable_buffer, 1> to_buffers() + { + std::array<asio::mutable_buffer, 1> buffers + = { { asio::buffer(data_) } }; + return buffers; + } + +private: + // The length in bytes of a frame and its components. + enum + { + encoded_number_size = 8, // Frame number in hex. + frame_size = encoded_number_size + payload_size + }; + + // The encoded frame data. + char data_[frame_size]; +}; + +#endif // PORTHOPPER_PROTOCOL_HPP diff --git a/3rdparty/asio/src/examples/cpp11/porthopper/server.cpp b/3rdparty/asio/src/examples/cpp11/porthopper/server.cpp new file mode 100644 index 00000000000..4a77622e593 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/porthopper/server.cpp @@ -0,0 +1,187 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <cmath> +#include <cstdlib> +#include <exception> +#include <functional> +#include <iostream> +#include <memory> +#include <set> +#include "protocol.hpp" + +using asio::ip::tcp; +using asio::ip::udp; + +typedef std::shared_ptr<tcp::socket> tcp_socket_ptr; +typedef std::shared_ptr<asio::steady_timer> timer_ptr; +typedef std::shared_ptr<control_request> control_request_ptr; + +class server +{ +public: + // Construct the server to wait for incoming control connections. + server(asio::io_context& io_context, unsigned short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), + timer_(io_context), + udp_socket_(io_context, udp::endpoint(udp::v4(), 0)), + next_frame_number_(1) + { + // Start waiting for a new control connection. + tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_executor())); + acceptor_.async_accept(*new_socket, + std::bind(&server::handle_accept, this, + asio::placeholders::error, new_socket)); + + // Start the timer used to generate outgoing frames. + timer_.expires_after(asio::chrono::milliseconds(100)); + timer_.async_wait(std::bind(&server::handle_timer, this)); + } + + // Handle a new control connection. + void handle_accept(const std::error_code& ec, tcp_socket_ptr socket) + { + if (!ec) + { + // Start receiving control requests on the connection. + control_request_ptr request(new control_request); + asio::async_read(*socket, request->to_buffers(), + std::bind(&server::handle_control_request, this, + asio::placeholders::error, socket, request)); + } + + // Start waiting for a new control connection. + tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_executor())); + acceptor_.async_accept(*new_socket, + std::bind(&server::handle_accept, this, + asio::placeholders::error, new_socket)); + } + + // Handle a new control request. + void handle_control_request(const std::error_code& ec, + tcp_socket_ptr socket, control_request_ptr request) + { + if (!ec) + { + // Delay handling of the control request to simulate network latency. + timer_ptr delay_timer( + new asio::steady_timer(acceptor_.get_executor())); + delay_timer->expires_after(asio::chrono::seconds(2)); + delay_timer->async_wait( + std::bind(&server::handle_control_request_timer, this, + socket, request, delay_timer)); + } + } + + void handle_control_request_timer(tcp_socket_ptr socket, + control_request_ptr request, timer_ptr /*delay_timer*/) + { + // Determine what address this client is connected from, since + // subscriptions must be stored on the server as a complete endpoint, not + // just a port. We use the non-throwing overload of remote_endpoint() since + // it may fail if the socket is no longer connected. + std::error_code ec; + tcp::endpoint remote_endpoint = socket->remote_endpoint(ec); + if (!ec) + { + // Remove old port subscription, if any. + if (unsigned short old_port = request->old_port()) + { + udp::endpoint old_endpoint(remote_endpoint.address(), old_port); + subscribers_.erase(old_endpoint); + std::cout << "Removing subscription " << old_endpoint << std::endl; + } + + // Add new port subscription, if any. + if (unsigned short new_port = request->new_port()) + { + udp::endpoint new_endpoint(remote_endpoint.address(), new_port); + subscribers_.insert(new_endpoint); + std::cout << "Adding subscription " << new_endpoint << std::endl; + } + } + + // Wait for next control request on this connection. + asio::async_read(*socket, request->to_buffers(), + std::bind(&server::handle_control_request, this, + asio::placeholders::error, socket, request)); + } + + // Every time the timer fires we will generate a new frame and send it to all + // subscribers. + void handle_timer() + { + // Generate payload. + double x = next_frame_number_ * 0.2; + double y = std::sin(x); + int char_index = static_cast<int>((y + 1.0) * (frame::payload_size / 2)); + std::string payload; + for (int i = 0; i < frame::payload_size; ++i) + payload += (i == char_index ? '*' : '.'); + + // Create the frame to be sent to all subscribers. + frame f(next_frame_number_++, payload); + + // Send frame to all subscribers. We can use synchronous calls here since + // UDP send operations typically do not block. + std::set<udp::endpoint>::iterator j; + for (j = subscribers_.begin(); j != subscribers_.end(); ++j) + { + std::error_code ec; + udp_socket_.send_to(f.to_buffers(), *j, 0, ec); + } + + // Wait for next timeout. + timer_.expires_after(asio::chrono::milliseconds(100)); + timer_.async_wait(std::bind(&server::handle_timer, this)); + } + +private: + // The acceptor used to accept incoming control connections. + tcp::acceptor acceptor_; + + // The timer used for generating data. + asio::steady_timer timer_; + + // The socket used to send data to subscribers. + udp::socket udp_socket_; + + // The next frame number. + unsigned long next_frame_number_; + + // The set of endpoints that are subscribed. + std::set<udp::endpoint> subscribers_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: server <port>\n"; + return 1; + } + + asio::io_context io_context; + + using namespace std; // For atoi. + server s(io_context, atoi(argv[1])); + + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/serialization/client.cpp b/3rdparty/asio/src/examples/cpp11/serialization/client.cpp new file mode 100644 index 00000000000..10ec87f6da4 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/serialization/client.cpp @@ -0,0 +1,125 @@ +// +// client.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <functional> +#include <iostream> +#include <vector> +#include "connection.hpp" // Must come before boost/serialization headers. +#include <boost/serialization/vector.hpp> +#include "stock.hpp" + +namespace s11n_example { + +/// Downloads stock quote information from a server. +class client +{ +public: + /// Constructor starts the asynchronous connect operation. + client(asio::io_context& io_context, + const std::string& host, const std::string& service) + : connection_(io_context.get_executor()) + { + // Resolve the host name into an IP address. + asio::ip::tcp::resolver resolver(io_context); + asio::ip::tcp::resolver::query query(host, service); + asio::ip::tcp::resolver::iterator endpoint_iterator = + resolver.resolve(query); + + // Start an asynchronous connect operation. + asio::async_connect(connection_.socket(), endpoint_iterator, + std::bind(&client::handle_connect, this, + asio::placeholders::error)); + } + + /// Handle completion of a connect operation. + void handle_connect(const asio::error_code& e) + { + if (!e) + { + // Successfully established connection. Start operation to read the list + // of stocks. The connection::async_read() function will automatically + // decode the data that is read from the underlying socket. + connection_.async_read(stocks_, + std::bind(&client::handle_read, this, + asio::placeholders::error)); + } + else + { + // An error occurred. Log it and return. Since we are not starting a new + // operation the io_context will run out of work to do and the client will + // exit. + std::cerr << e.message() << std::endl; + } + } + + /// Handle completion of a read operation. + void handle_read(const asio::error_code& e) + { + if (!e) + { + // Print out the data that was received. + for (std::size_t i = 0; i < stocks_.size(); ++i) + { + std::cout << "Stock number " << i << "\n"; + std::cout << " code: " << stocks_[i].code << "\n"; + std::cout << " name: " << stocks_[i].name << "\n"; + std::cout << " open_price: " << stocks_[i].open_price << "\n"; + std::cout << " high_price: " << stocks_[i].high_price << "\n"; + std::cout << " low_price: " << stocks_[i].low_price << "\n"; + std::cout << " last_price: " << stocks_[i].last_price << "\n"; + std::cout << " buy_price: " << stocks_[i].buy_price << "\n"; + std::cout << " buy_quantity: " << stocks_[i].buy_quantity << "\n"; + std::cout << " sell_price: " << stocks_[i].sell_price << "\n"; + std::cout << " sell_quantity: " << stocks_[i].sell_quantity << "\n"; + } + } + else + { + // An error occurred. + std::cerr << e.message() << std::endl; + } + + // Since we are not starting a new operation the io_context will run out of + // work to do and the client will exit. + } + +private: + /// The connection to the server. + connection connection_; + + /// The data received from the server. + std::vector<stock> stocks_; +}; + +} // namespace s11n_example + +int main(int argc, char* argv[]) +{ + try + { + // Check command line arguments. + if (argc != 3) + { + std::cerr << "Usage: client <host> <port>" << std::endl; + return 1; + } + + asio::io_context io_context; + s11n_example::client client(io_context, argv[1], argv[2]); + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/serialization/connection.hpp b/3rdparty/asio/src/examples/cpp11/serialization/connection.hpp new file mode 100644 index 00000000000..14d96f7597b --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/serialization/connection.hpp @@ -0,0 +1,184 @@ +// +// connection.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 SERIALIZATION_CONNECTION_HPP +#define SERIALIZATION_CONNECTION_HPP + +#include <asio.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/archive/text_oarchive.hpp> +#include <functional> +#include <iomanip> +#include <memory> +#include <string> +#include <sstream> +#include <tuple> +#include <vector> + +namespace s11n_example { + +/// The connection class provides serialization primitives on top of a socket. +/** + * Each message sent using this class consists of: + * @li An 8-byte header containing the length of the serialized data in + * hexadecimal. + * @li The serialized data. + */ +class connection +{ +public: + /// Constructor. + connection(const asio::any_io_executor& ex) + : socket_(ex) + { + } + + /// Get the underlying socket. Used for making a connection or for accepting + /// an incoming connection. + asio::ip::tcp::socket& socket() + { + return socket_; + } + + /// Asynchronously write a data structure to the socket. + template <typename T, typename Handler> + void async_write(const T& t, Handler handler) + { + // Serialize the data first so we know how large it is. + std::ostringstream archive_stream; + boost::archive::text_oarchive archive(archive_stream); + archive << t; + outbound_data_ = archive_stream.str(); + + // Format the header. + std::ostringstream header_stream; + header_stream << std::setw(header_length) + << std::hex << outbound_data_.size(); + if (!header_stream || header_stream.str().size() != header_length) + { + // Something went wrong, inform the caller. + std::error_code error(asio::error::invalid_argument); + asio::post(socket_.get_executor(), std::bind(handler, error)); + return; + } + outbound_header_ = header_stream.str(); + + // Write the serialized data to the socket. We use "gather-write" to send + // both the header and the data in a single write operation. + std::vector<asio::const_buffer> buffers; + buffers.push_back(asio::buffer(outbound_header_)); + buffers.push_back(asio::buffer(outbound_data_)); + asio::async_write(socket_, buffers, handler); + } + + /// Asynchronously read a data structure from the socket. + template <typename T, typename Handler> + void async_read(T& t, Handler handler) + { + // Issue a read operation to read exactly the number of bytes in a header. + void (connection::*f)(const std::error_code&, T&, std::tuple<Handler>) + = &connection::handle_read_header<T, Handler>; + asio::async_read(socket_, asio::buffer(inbound_header_), + std::bind(f, + this, asio::placeholders::error, std::ref(t), + std::make_tuple(handler))); + } + + /// Handle a completed read of a message header. + template <typename T, typename Handler> + void handle_read_header(const std::error_code& e, + T& t, std::tuple<Handler> handler) + { + if (e) + { + std::get<0>(handler)(e); + } + else + { + // Determine the length of the serialized data. + std::istringstream is(std::string(inbound_header_, header_length)); + std::size_t inbound_data_size = 0; + if (!(is >> std::hex >> inbound_data_size)) + { + // Header doesn't seem to be valid. Inform the caller. + std::error_code error(asio::error::invalid_argument); + std::get<0>(handler)(error); + return; + } + + // Start an asynchronous call to receive the data. + inbound_data_.resize(inbound_data_size); + void (connection::*f)( + const std::error_code&, + T&, std::tuple<Handler>) + = &connection::handle_read_data<T, Handler>; + asio::async_read(socket_, asio::buffer(inbound_data_), + std::bind(f, this, + asio::placeholders::error, std::ref(t), handler)); + } + } + + /// Handle a completed read of message data. + template <typename T, typename Handler> + void handle_read_data(const std::error_code& e, + T& t, std::tuple<Handler> handler) + { + if (e) + { + std::get<0>(handler)(e); + } + else + { + // Extract the data structure from the data just received. + try + { + std::string archive_data(&inbound_data_[0], inbound_data_.size()); + std::istringstream archive_stream(archive_data); + boost::archive::text_iarchive archive(archive_stream); + archive >> t; + } + catch (std::exception& e) + { + // Unable to decode data. + std::error_code error(asio::error::invalid_argument); + std::get<0>(handler)(error); + return; + } + + // Inform caller that data has been received ok. + std::get<0>(handler)(e); + } + } + +private: + /// The underlying socket. + asio::ip::tcp::socket socket_; + + /// The size of a fixed length header. + enum { header_length = 8 }; + + /// Holds an outbound header. + std::string outbound_header_; + + /// Holds the outbound data. + std::string outbound_data_; + + /// Holds an inbound header. + char inbound_header_[header_length]; + + /// Holds the inbound data. + std::vector<char> inbound_data_; +}; + +typedef std::shared_ptr<connection> connection_ptr; + +} // namespace s11n_example + +#endif // SERIALIZATION_CONNECTION_HPP diff --git a/3rdparty/asio/src/examples/cpp11/serialization/server.cpp b/3rdparty/asio/src/examples/cpp11/serialization/server.cpp new file mode 100644 index 00000000000..a032e86dc78 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/serialization/server.cpp @@ -0,0 +1,122 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <functional> +#include <iostream> +#include <vector> +#include "connection.hpp" // Must come before boost/serialization headers. +#include <boost/serialization/vector.hpp> +#include "stock.hpp" + +namespace s11n_example { + +/// Serves stock quote information to any client that connects to it. +class server +{ +public: + /// Constructor opens the acceptor and starts waiting for the first incoming + /// connection. + server(asio::io_context& io_context, unsigned short port) + : acceptor_(io_context, + asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port)) + { + // Create the data to be sent to each client. + stock s; + s.code = "ABC"; + s.name = "A Big Company"; + s.open_price = 4.56; + s.high_price = 5.12; + s.low_price = 4.33; + s.last_price = 4.98; + s.buy_price = 4.96; + s.buy_quantity = 1000; + s.sell_price = 4.99; + s.sell_quantity = 2000; + stocks_.push_back(s); + s.code = "DEF"; + s.name = "Developer Entertainment Firm"; + s.open_price = 20.24; + s.high_price = 22.88; + s.low_price = 19.50; + s.last_price = 19.76; + s.buy_price = 19.72; + s.buy_quantity = 34000; + s.sell_price = 19.85; + s.sell_quantity = 45000; + stocks_.push_back(s); + + // Start an accept operation for a new connection. + connection_ptr new_conn(new connection(acceptor_.get_executor())); + acceptor_.async_accept(new_conn->socket(), + std::bind(&server::handle_accept, this, + asio::placeholders::error, new_conn)); + } + + /// Handle completion of a accept operation. + void handle_accept(const std::error_code& e, connection_ptr conn) + { + if (!e) + { + // Successfully accepted a new connection. Send the list of stocks to the + // client. The connection::async_write() function will automatically + // serialize the data structure for us. + conn->async_write(stocks_, + std::bind(&server::handle_write, this, + asio::placeholders::error, conn)); + } + + // Start an accept operation for a new connection. + connection_ptr new_conn(new connection(acceptor_.get_executor())); + acceptor_.async_accept(new_conn->socket(), + std::bind(&server::handle_accept, this, + asio::placeholders::error, new_conn)); + } + + /// Handle completion of a write operation. + void handle_write(const std::error_code& e, connection_ptr conn) + { + // Nothing to do. The socket will be closed automatically when the last + // reference to the connection object goes away. + } + +private: + /// The acceptor object used to accept incoming socket connections. + asio::ip::tcp::acceptor acceptor_; + + /// The data to be sent to each client. + std::vector<stock> stocks_; +}; + +} // namespace s11n_example + +int main(int argc, char* argv[]) +{ + try + { + // Check command line arguments. + if (argc != 2) + { + std::cerr << "Usage: server <port>" << std::endl; + return 1; + } + unsigned short port = std::stoi(argv[1]); + + asio::io_context io_context; + s11n_example::server server(io_context, port); + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/serialization/stock.hpp b/3rdparty/asio/src/examples/cpp11/serialization/stock.hpp new file mode 100644 index 00000000000..bb305518cae --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/serialization/stock.hpp @@ -0,0 +1,50 @@ +// +// stock.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 SERIALIZATION_STOCK_HPP +#define SERIALIZATION_STOCK_HPP + +#include <string> + +namespace s11n_example { + +/// Structure to hold information about a single stock. +struct stock +{ + std::string code; + std::string name; + double open_price; + double high_price; + double low_price; + double last_price; + double buy_price; + int buy_quantity; + double sell_price; + int sell_quantity; + + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & code; + ar & name; + ar & open_price; + ar & high_price; + ar & low_price; + ar & last_price; + ar & buy_price; + ar & buy_quantity; + ar & sell_price; + ar & sell_quantity; + } +}; + +} // namespace s11n_example + +#endif // SERIALIZATION_STOCK_HPP diff --git a/3rdparty/asio/src/examples/cpp11/services/basic_logger.hpp b/3rdparty/asio/src/examples/cpp11/services/basic_logger.hpp new file mode 100644 index 00000000000..6e4d7a0b05d --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/services/basic_logger.hpp @@ -0,0 +1,78 @@ +// +// basic_logger.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 SERVICES_BASIC_LOGGER_HPP +#define SERVICES_BASIC_LOGGER_HPP + +#include <asio.hpp> +#include <string> + +namespace services { + +/// Class to provide simple logging functionality. Use the services::logger +/// typedef. +template <typename Service> +class basic_logger +{ +public: + /// The type of the service that will be used to provide timer operations. + typedef Service service_type; + + /// The native implementation type of the timer. + typedef typename service_type::impl_type impl_type; + + /// Constructor. + /** + * This constructor creates a logger. + * + * @param context The execution context used to locate the logger service. + * + * @param identifier An identifier for this logger. + */ + explicit basic_logger(asio::execution_context& context, + const std::string& identifier) + : service_(asio::use_service<Service>(context)), + impl_(service_.null()) + { + service_.create(impl_, identifier); + } + + basic_logger(const basic_logger&) = delete; + basic_logger& operator=(basic_logger&) = delete; + + /// Destructor. + ~basic_logger() + { + service_.destroy(impl_); + } + + /// Set the output file for all logger instances. + void use_file(const std::string& file) + { + service_.use_file(impl_, file); + } + + /// Log a message. + void log(const std::string& message) + { + service_.log(impl_, message); + } + +private: + /// The backend service implementation. + service_type& service_; + + /// The underlying native implementation. + impl_type impl_; +}; + +} // namespace services + +#endif // SERVICES_BASIC_LOGGER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/services/daytime_client.cpp b/3rdparty/asio/src/examples/cpp11/services/daytime_client.cpp new file mode 100644 index 00000000000..360134f64c2 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/services/daytime_client.cpp @@ -0,0 +1,101 @@ +// +// daytime_client.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <asio.hpp> +#include <functional> +#include <iostream> +#include "logger.hpp" + +using asio::ip::tcp; + +char read_buffer[1024]; + +void read_handler(const asio::error_code& e, + std::size_t bytes_transferred, tcp::socket* s) +{ + if (!e) + { + std::cout.write(read_buffer, bytes_transferred); + + s->async_read_some(asio::buffer(read_buffer), + std::bind(read_handler, asio::placeholders::error, + asio::placeholders::bytes_transferred, s)); + } + else + { + asio::execution_context& context = asio::query( + s->get_executor(), asio::execution::context); + services::logger logger(context, "read_handler"); + + std::string msg = "Read error: "; + msg += e.message(); + logger.log(msg); + } +} + +void connect_handler(const asio::error_code& e, tcp::socket* s) +{ + asio::execution_context& context = asio::query( + s->get_executor(), asio::execution::context); + services::logger logger(context, "connect_handler"); + + if (!e) + { + logger.log("Connection established"); + + s->async_read_some(asio::buffer(read_buffer), + std::bind(read_handler, asio::placeholders::error, + asio::placeholders::bytes_transferred, s)); + } + else + { + std::string msg = "Unable to establish connection: "; + msg += e.message(); + logger.log(msg); + } +} + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: daytime_client <host>" << std::endl; + return 1; + } + + asio::io_context io_context; + + // Set the name of the file that all logger instances will use. + services::logger logger(io_context, ""); + logger.use_file("log.txt"); + + // Resolve the address corresponding to the given host. + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = + resolver.resolve(argv[1], "daytime"); + + // Start an asynchronous connect. + tcp::socket socket(io_context); + asio::async_connect(socket, endpoints, + std::bind(connect_handler, + asio::placeholders::error, &socket)); + + // Run the io_context until all operations have finished. + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/services/logger.hpp b/3rdparty/asio/src/examples/cpp11/services/logger.hpp new file mode 100644 index 00000000000..2ab366c83c6 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/services/logger.hpp @@ -0,0 +1,24 @@ +// +// logger.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 SERVICES_LOGGER_HPP +#define SERVICES_LOGGER_HPP + +#include "basic_logger.hpp" +#include "logger_service.hpp" + +namespace services { + +/// Typedef for typical logger usage. +typedef basic_logger<logger_service> logger; + +} // namespace services + +#endif // SERVICES_LOGGER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/services/logger_service.cpp b/3rdparty/asio/src/examples/cpp11/services/logger_service.cpp new file mode 100644 index 00000000000..74d67c75241 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/services/logger_service.cpp @@ -0,0 +1,11 @@ +// +// logger_service.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "logger_service.hpp" diff --git a/3rdparty/asio/src/examples/cpp11/services/logger_service.hpp b/3rdparty/asio/src/examples/cpp11/services/logger_service.hpp new file mode 100644 index 00000000000..d0beaf1d6c2 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/services/logger_service.hpp @@ -0,0 +1,145 @@ +// +// logger_service.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 SERVICES_LOGGER_SERVICE_HPP +#define SERVICES_LOGGER_SERVICE_HPP + +#include <asio.hpp> +#include <functional> +#include <fstream> +#include <sstream> +#include <string> +#include <thread> + +namespace services { + +/// Service implementation for the logger. +class logger_service + : public asio::execution_context::service +{ +public: + /// The type used to identify this service in the execution context. + typedef logger_service key_type; + + /// The backend implementation of a logger. + struct logger_impl + { + explicit logger_impl(const std::string& ident) : identifier(ident) {} + std::string identifier; + }; + + /// The type for an implementation of the logger. + typedef logger_impl* impl_type; + + /// Constructor creates a thread to run a private io_context. + logger_service(asio::execution_context& context) + : asio::execution_context::service(context), + work_io_context_(), + work_(asio::make_work_guard(work_io_context_)), + work_thread_([this]{ work_io_context_.run(); }) + { + } + + logger_service(const logger_service&) = delete; + logger_service& operator=(const logger_service&) = delete;; + + /// Destructor shuts down the private io_context. + ~logger_service() + { + /// Indicate that we have finished with the private io_context. Its + /// io_context::run() function will exit once all other work has completed. + work_.reset(); + if (work_thread_.joinable()) + work_thread_.join(); + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown() + { + } + + /// Return a null logger implementation. + impl_type null() const + { + return 0; + } + + /// Create a new logger implementation. + void create(impl_type& impl, const std::string& identifier) + { + impl = new logger_impl(identifier); + } + + /// Destroy a logger implementation. + void destroy(impl_type& impl) + { + delete impl; + impl = null(); + } + + /// Set the output file for the logger. The current implementation sets the + /// output file for all logger instances, and so the impl parameter is not + /// actually needed. It is retained here to illustrate how service functions + /// are typically defined. + void use_file(impl_type& /*impl*/, const std::string& file) + { + // Pass the work of opening the file to the background thread. + asio::post(work_io_context_, + std::bind(&logger_service::use_file_impl, this, file)); + } + + /// Log a message. + void log(impl_type& impl, const std::string& message) + { + // Format the text to be logged. + std::ostringstream os; + os << impl->identifier << ": " << message; + + // Pass the work of writing to the file to the background thread. + asio::post(work_io_context_, + std::bind(&logger_service::log_impl, this, os.str())); + } + +private: + /// Helper function used to open the output file from within the private + /// io_context's thread. + void use_file_impl(const std::string& file) + { + ofstream_.close(); + ofstream_.clear(); + ofstream_.open(file.c_str()); + } + + /// Helper function used to log a message from within the private io_context's + /// thread. + void log_impl(const std::string& text) + { + ofstream_ << text << std::endl; + } + + /// Private io_context used for performing logging operations. + asio::io_context work_io_context_; + + /// Work for the private io_context to perform. If we do not give the + /// io_context some work to do then the io_context::run() function will exit + /// immediately. + asio::executor_work_guard< + asio::io_context::executor_type> work_; + + /// Thread used for running the work io_context's run loop. + std::thread work_thread_; + + /// The file to which log messages will be written. + std::ofstream ofstream_; +}; + +} // namespace services + +#endif // SERVICES_LOGGER_SERVICE_HPP diff --git a/3rdparty/asio/src/examples/cpp11/socks4/socks4.hpp b/3rdparty/asio/src/examples/cpp11/socks4/socks4.hpp index 4287b3f1948..ed7994021fc 100644 --- a/3rdparty/asio/src/examples/cpp11/socks4/socks4.hpp +++ b/3rdparty/asio/src/examples/cpp11/socks4/socks4.hpp @@ -2,7 +2,7 @@ // socks4.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -39,7 +39,7 @@ public: // Only IPv4 is supported by the SOCKS 4 protocol. if (endpoint.protocol() != asio::ip::tcp::v4()) { - throw asio::system_error( + throw std::system_error( asio::error::address_family_not_supported); } diff --git a/3rdparty/asio/src/examples/cpp11/socks4/sync_client.cpp b/3rdparty/asio/src/examples/cpp11/socks4/sync_client.cpp index e0d20992fe2..f661aca8da5 100644 --- a/3rdparty/asio/src/examples/cpp11/socks4/sync_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/socks4/sync_client.cpp @@ -2,7 +2,7 @@ // sync_client.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/spawn/echo_server.cpp b/3rdparty/asio/src/examples/cpp11/spawn/echo_server.cpp index 95adffd604e..ae949d60bef 100644 --- a/3rdparty/asio/src/examples/cpp11/spawn/echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp11/spawn/echo_server.cpp @@ -2,12 +2,13 @@ // echo_server.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // +#include <asio/detached.hpp> #include <asio/io_context.hpp> #include <asio/ip/tcp.hpp> #include <asio/spawn.hpp> @@ -39,7 +40,7 @@ public: char data[128]; for (;;) { - timer_.expires_from_now(std::chrono::seconds(10)); + timer_.expires_after(std::chrono::seconds(10)); std::size_t n = socket_.async_read_some(asio::buffer(data), yield); asio::async_write(socket_, asio::buffer(data, n), yield); } @@ -49,19 +50,19 @@ public: socket_.close(); timer_.cancel(); } - }); + }, asio::detached); asio::spawn(strand_, [this, self](asio::yield_context yield) { while (socket_.is_open()) { - asio::error_code ignored_ec; + std::error_code ignored_ec; timer_.async_wait(yield[ignored_ec]); - if (timer_.expires_from_now() <= std::chrono::seconds(0)) + if (timer_.expiry() <= asio::steady_timer::clock_type::now()) socket_.close(); } - }); + }, asio::detached); } private: @@ -90,7 +91,7 @@ int main(int argc, char* argv[]) for (;;) { - asio::error_code ec; + std::error_code ec; tcp::socket socket(io_context); acceptor.async_accept(socket, yield[ec]); if (!ec) @@ -98,6 +99,11 @@ int main(int argc, char* argv[]) std::make_shared<session>(io_context, std::move(socket))->go(); } } + }, + [](std::exception_ptr e) + { + if (e) + std::rethrow_exception(e); }); io_context.run(); diff --git a/3rdparty/asio/src/examples/cpp11/spawn/parallel_grep.cpp b/3rdparty/asio/src/examples/cpp11/spawn/parallel_grep.cpp index fc2c6ecd1c2..f4a5b1136dc 100644 --- a/3rdparty/asio/src/examples/cpp11/spawn/parallel_grep.cpp +++ b/3rdparty/asio/src/examples/cpp11/spawn/parallel_grep.cpp @@ -2,12 +2,13 @@ // parallel_grep.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) // +#include <asio/detached.hpp> #include <asio/dispatch.hpp> #include <asio/post.hpp> #include <asio/spawn.hpp> @@ -17,6 +18,7 @@ #include <iostream> #include <string> +using asio::detached; using asio::dispatch; using asio::spawn; using asio::strand; @@ -69,7 +71,7 @@ int main(int argc, char* argv[]) if (++line_num % 10 == 0) post(yield); } - }); + }, detached); } // Join the thread pool to wait for all the spawned tasks to complete. diff --git a/3rdparty/asio/src/examples/cpp11/ssl/README b/3rdparty/asio/src/examples/cpp11/ssl/README new file mode 100644 index 00000000000..8304d0603b6 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/ssl/README @@ -0,0 +1,8 @@ +The passphrase for both the CA and server private keys is "test". + + +------------------------------------------------------------------------------- +Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/ssl/ca.pem b/3rdparty/asio/src/examples/cpp11/ssl/ca.pem new file mode 100644 index 00000000000..4580bc11bcf --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/ssl/ca.pem @@ -0,0 +1,50 @@ +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIUX3cVQ47QyJp7SOy0RPzP743W9MwwDQYJKoZIhvcNAQEL +BQAwOzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5 +MQ0wCwYDVQQKDARhc2lvMB4XDTIxMTExMTIxMTA1MloXDTI2MTExMDIxMTA1Mlow +OzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5MQ0w +CwYDVQQKDARhc2lvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyURD +LjKxTCkapmWhY0bP1NaaOPzIJTTB0dzREOlmRmBmiHpW7DaRx7qBm6jYDKQ7OCbz +30/j8K4TjHOLIwxzXhXMYTJOcN2giPHNUBvm9oEuDAhYgltArJQnBBEH+3C1hCIv +1+uhTWo0HpGXTeJnvboTZ1YgmbOgr6lMhNiu9QmPX885DxWf6sDq8mRgCDX2x8sk +Ls0HuLSo88Osjx532yEhnrZgexsByhoRD3yrKHV5mWpaunk5BMsP/XMuQHayFmbO +siqnHJoL1znGVH003PcBGmEDmoIUqhLiBi2gWGu1pmckP9loqQUTEn0aLOVclHf4 +slWq344zh4tJCpQMfQIDAQABo1AwTjAdBgNVHQ4EFgQUfiX1CMQrGDi9mIBAg9cg +m0RwLJUwHwYDVR0jBBgwFoAUfiX1CMQrGDi9mIBAg9cgm0RwLJUwDAYDVR0TBAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAnDnVNSb8z/pNFaZ6YAZ+ukfNT3jjbGm1 +10BOLqJj8s5A8/JkwjaWhky/DuGXDywgEvzXC18aNAxASeqO8h9pAZtszu6NWB4s +h3r+dEQakMacxrZ+jBL/cYLrUv9r3KMPKxaDnplkamqFA/9eNmoV7vDyGtGPZuD6 +oTROtQqqDSrxthCkqnibAfusi7RmlCdvJa0kVK7krKJZAhi8W9f32+lBPv9oq3Ns +dAxnOj/D3UnhNoIt0EdjqUdLo2U39dt5s5Syj2rFUAgfbc02Rwx65kq8AjTRlW/M +KDpGsifwIB8b7wActMUO8c3GptptNVWmFm5+Mmk54P//P3tIAx9KXw== +-----END CERTIFICATE----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIPcVUeQ7ZElgCAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECGKlFVN6/gIlBIIEyJPeknsA5dvV +WK27AZzs4wM6WrsD6ba+kPJyZTpon5pn4eoTiw4UCvo7C+21G9jCqbIbDrgTWHwH +zu6YrBFTZgRUpdLkLsyUsp4UJrZ8xJ7N/jWlG763CyluFE5oBFLz2Vt/DSDSaWdA +sKdxua/1kvw+KYoDqlObMFIspM5TrndcMnWkOgyvQAvnH0NZXFFBa4QGFrwWDrCo +m12CzMLwaPMrNFBffCTqZnL1AajT+EYqPTi+cQ5mkRpZ2cuzhdug2eki1KkD12ZN +3d8Ehl8bfbLEqRE/HnggleRRt7ia1xkzruqQp14JA2UsrioGMF5nvWgWrbyHfpui +KrCsDwDelrArW/GCki53QBQMuH8Q1YmoNrRZwlG257eA1LiJvmxRyIjKYu0RP+Q8 +EOldycy51VsPVPApUbv9r4IJldrIJiwlmRxxM36uKtFhfojnsWzJORDYI8C37uKi +UEPiD4GSEH6C0lGO94IoZPjl9z/rZ0qZx1VRHl3nxZc0AQvvj9bWMbyRwsgb6wod +P8JSy6uEib9UxuenNHzTd48GcNhJbhOqd4IV0XKhi8W1Kil3mMdc3QAwKaLTx12/ +1GrbMui061uyeM6Rf6Xao0PApDnUNmxcFSTsoarG0yH7Q0WZMgKTDCCGhhtZKlE6 +x7pRsnxiFaIpoh32EVIRI+ZXh2rXBcwa2ew0aEccRXtPFvcmdjevkrHuCggc+M+Y +seFqTHVGWf8eS6o08w095DboD0vFpZXZMRfycTbA7BiE4NYE/uc7v5cH3Ax9l2ef +zG7o9idDt+/RX7OcetxDFw4eQbq7PfjvrfXS1DcRUEyJ04emh7oxlkAUUNsFtabN +T0ggvHxcQWkYRE5oPlkbgpwKpK4LDcApXKFwCDKPur2W5Q7KHRfDLtSvZvYarJum +8j2pGpEis/bdTih29ofNsX6a0Yo5Tlj+9+1c/6/Xi7XvRk/Vbgkoa3iVQ3ckdCuZ +vO7cRYZBBs6W/Ti3hWFzPEX9FfcnSUp9bEnH4ASnmUcp8PDBJYeaI6HqpO3XbkbF +l70eDNakd2cDNjQzkFpBT7HO+HtqU3xNt9K0z2gMB7iTDVFyIzh26joCR2O8tiqS +wUJFkoLPb74GSB7WzE+gb4jXX6n9609PUoR3f896mM34uX3CsY8lA+/0ZGpHnFDA +ToKdmz6WKIAw0E20nyzLuLwPZgj7HLcR7zza4raipe9QxIdyJr5O+jzGt+OjSM9b +K1agibRE5DChqQ+P+ikOc6nG7UNyn+lKSjGEbwuzi8F0iugMgcTc/vYO8OWDNGpd +D1euA5OuVPdfatFa16Fyr4MJJIfE83C4/kSj05fdoyb6pJkOjHhUppVMe+ES5kwl +YI8RES2XVJzUSxnWsIM613YlMgIZ9xgcuIADnO7gaKJ4RQG+9wJ853Uo4+n89K7F +Y6KzihuYAUkbAw1pPo1TODom7A/gB9stqRUSQlZWmIgtnJ8wPjt/we0gzPM8LQzb +ye4KOLjH5iquFc4MU4TtN3gvp9P5R9UFrGeMImS5eMUmBQHckDNdIAtMj7M1wUpR +JVrzDXWDjC21sLn95NtNMPb+FRlt/biTV3IE3ZmX0kbuCRoH7b7hhR41Zpoajwl0 +FqYigB5gnVodGUWuBgDUqA== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/3rdparty/asio/src/examples/cpp11/ssl/client.cpp b/3rdparty/asio/src/examples/cpp11/ssl/client.cpp index 0ff7b00d0fd..6799d2a98e1 100644 --- a/3rdparty/asio/src/examples/cpp11/ssl/client.cpp +++ b/3rdparty/asio/src/examples/cpp11/ssl/client.cpp @@ -2,7 +2,7 @@ // client.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/ssl/dh4096.pem b/3rdparty/asio/src/examples/cpp11/ssl/dh4096.pem new file mode 100644 index 00000000000..dc2559c5f82 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/ssl/dh4096.pem @@ -0,0 +1,25 @@ +-----BEGIN X9.42 DH PARAMETERS----- +MIIELQKCAgEA8eEBgatlTk0QKIwUqHsteHJXzEr0xAW7RLeNid8DdGjTnFw68eV+ +s1YbipEqQVTFG+VZPaof9v0CH2KOdbgWD0KRPC49HB8O/wARFKpy5eJltVe1r07w ++V1Vjciqkh/vGq/yFQsbqwyWJy6AelsbHdSC9Bg9pmu4+pbVGW15zK7PkfjfoO9V +JYbhdqFIPg+9NRRWsl/U9UoyeeIGImI9I4k3fqtv311C6VVErFZylCj7nn45L7IY +GfPcCO5E8FD6EqBv5WnhMNYHMJu9brRvOoAyAyWprqR+aVzHd+DFamDQdsuQjKTk +3+r07znWJfjp6FVTzR5SvjrKg1knK5TibIksoKOlsFZ06bGkFWHjqXNAKhnSpCiU +GJd0qe7pTD+TGQJGWskJpoph+tkICUa+6MyzP9+U6T9hISIY/BpVuWn/iwdLqsvV +s5bg2RjRraww/4Rjm0NyEOTk2MxaLB9gcyu6zcrhX5XRiMgt+jhKwEMwJCEJYkxn +C0yv08A5v6RceFm1jY+8FT0IzRqsWIGV7beNdqtE0B4LBTuN1yQ6x8CKEb6mbIHG +d0XLGppELhD8QUwAr5HiVGTAsS9JlMGgXVkyDtxrVSeS1zHWt77skRQ9UlfJfYMm +5wxHj5QCdQ7ma3oMMZBZutNlkevMzYHIxwqhZstf4ud0j0VMftwZ3GMCggIBAJL7 +cU6/YSxzYDGUcPc6WGT+FAghR0LdhT3Q3Xz1rQRBwSSMPm9NZhyJC3fb+hBl/44X +AHOu1/3dYIWlXPMuHZZdtlt+hkD/sIob16By20Z0p81Kvh3HQglVDJGlFzTmQbTd +CM/EP8eJFiNeMcJB0RgeKyzikRsV4r/acZZM56swTlsRvSDFMh3v9YyYTZbCTwxm +PIVOsxI8uBoWRCzY3yWzjmlZ2u5TR+Z0IVonmNqk6XAKRgxV12YfQVXzzpPZQA9S +GHoD/NQoMdBAi3p4pLEYJ5qMRLYPQbBfSNu5eP9e5uZOiBp/28bVnzEelDGuFupr +lvywkZEVL1KaYtZ/dGkPFXt+A7mNsw5xeDTRjgL4uUJvCNIkjgVEfIrLdUf5IVsU +V8BgunAvgfH+Hy6Tx89v/QGsUWJPhjkSZnXwJ7Ipcsm+Zg0zAZwKDZEQtDLXVPRL +OfCfXMXvlw2u6OHlhSbqO69zZG3dJTlcnjy06n4JYcUim7Mj3Kduige6VWofeEk9 +M/kHrPqNdFE5tHLh2nHcw9yExKHN+l/OUGAvNDfOVS+S+fNSKT0RfC9dMpHLN+Ok +fGuskGzLQAVYF+DYEcnJ++0LEFtd0J381ndSc0iJuH60rKDTqxoRqv7lcdwLFlEV +sQSRoas8s+y+b3FfSu7j0p44qLG9oxZ/WFcWnuUyAiEAjvAD9p3bw8AH0s7dUrX/ +RT1Ge+J/n0tlsgw+LY3zafE= +-----END X9.42 DH PARAMETERS----- diff --git a/3rdparty/asio/src/examples/cpp11/ssl/server.cpp b/3rdparty/asio/src/examples/cpp11/ssl/server.cpp index 26ef44a31a5..15e0d9eaf03 100644 --- a/3rdparty/asio/src/examples/cpp11/ssl/server.cpp +++ b/3rdparty/asio/src/examples/cpp11/ssl/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -88,7 +88,7 @@ public: context_.set_password_callback(std::bind(&server::get_password, this)); context_.use_certificate_chain_file("server.pem"); context_.use_private_key_file("server.pem", asio::ssl::context::pem); - context_.use_tmp_dh_file("dh2048.pem"); + context_.use_tmp_dh_file("dh4096.pem"); do_accept(); } diff --git a/3rdparty/asio/src/examples/cpp11/ssl/server.pem b/3rdparty/asio/src/examples/cpp11/ssl/server.pem new file mode 100644 index 00000000000..a7bcba738a0 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/ssl/server.pem @@ -0,0 +1,99 @@ +-----BEGIN CERTIFICATE----- +MIIDDjCCAfYCFGGcJXlIeQHiq/qOakbISU5cihPvMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTENMAsG +A1UECgwEYXNpbzAeFw0yMTExMTEyMTExNDRaFw0yNjExMTAyMTExNDRaMEwxCzAJ +BgNVBAYTAkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTENMAsGA1UE +CgwEYXNpbzEPMA0GA1UECwwGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAu67TzZCFNTZ5c1gKwXfdTH3bP0OB5n6dqXGK6jkPb699dyM4oPtY +2f+OyxJspk8D5pX6HuZ+hLGAsHxfCN+A3RegVZJCR/gXrrMPl/6PfDxtkeFXWy+6 +NAPxqppMj8gbX/czTdNFwgW4J8/RLyH53utjAGQtCRr97EbBOsTSeOmyAxbw4mRt +EvHjacKFcSZzJDlyxCia37791MulZ4lwOZZlke5NzoOqkBIAusQgg7fMWDvH27PD +T+taIyBsYTVJWHf5kMklAlWYXZvNjZp/QGt13lDORg2aSc/P2pE4iLyhbZcpuW+W +nHB7IY1wjDL55/ORCjz3VlNIAMXHP5YQxwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB +AQC3iiwQTgDP4ixulisYIGlJb8iuhxH9G41hm8dF/1qlIfXWxsbjb+g7M5U/3JCb +fwCGoz7uBdj/CKkIb5wx83GVC1yVLbNSvCIS827qxic4GACEYGGAy4Ub5tUCQrLr +JUQTP1WVJcgiKvk7OAcXdA+k/CcNXH153gUPDZz+/BedXe2VbM6LDsqPeSxXfbZN +AWXARAuly7cQk/xkYkPldRRhx4htNCbnkG1qyEqNcYQN1SY9Qhbrm2HkAUntzQ7G +umo4JdbIX6MJ5fYNs+yN/lJB7PiJP8Mz1AtOz4x9JxcLyuB6sapT8Tj53n9g/+m1 +Tqd8lHpWe6oM0sgdWfzdBNir +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9E0E6B9970E055F1 + +oFvN3t50B2TSeNsRo1vwhVYlMmt0w3MD3Ar75fti4fRhBrWoH4rBPrSouWK4OMDK +CakfVhzJIEvaMav843grS4V+ooAsfnAtiQiQj+5xjZ8PlCuWir5gyjgqeN4zN6ZT +2s/oEy5Kx7Ru5AWMkv+NPW5l3iS3c+Hupfb/auITwECSCCsCBxgNtJ8z0iXjv9Dr +hqvqcI+4F5DSiol3QhitbpQ/k2PKu92AZhPcr9e5HrqeUD7aqfX2q3i+tnJvxC93 +0mvy133bX2ZAGAKMheW/GuzcETfwU80wvmrwHXI9rnuAUaJhrDiIZQ79gubZ0Pcm +w4Y6Z5xxeErb7zKBi+pHKst8MJ7rfSz/N878su6cpESRC/w1paVX7m8/q61kzBkj ++h2qe9DupXBejQkriN+Z858nFtBKbWlFsmAg1FLZonworTUfV2c7S9yzMV/29VOE +T0Bt8BU1Hp+bCjreF4JGbnUJnRQoASpisfUkrD6Ar4GI56Edkkx6hkF0cXdcvfCN +qyhxzcvf/aV1M2kcpBRX9mIfjoFMFNz7uRIxyqPLaDkigwJemoaBo3n9/W5F7N7B +AGNEZ3QhUlc8EyWpGRZRzMevu5wdz1b2+MqItOhPXUo2XcLEj2iFkVDdbj/d9jQH +9ZIe4hQTSf784tAzt2Jp2RHmm22390GB1jdzG/CzbGlAKmaTTEe4FJcd/eLOEZuD +4+iFsEb/bWcCyXkBKkdEoDDMJW8xi5d/1ezJM03nqhvkekDqyhJUJPCbmY1SCX1X +4AO40jJmWQxwj26Pnnncacz4tuecZNqovz+POpKQSIctrQSV4wgf35137KBt7/O7 +EU0N7Qj4xTigyGkEHCZt7BgD8fFrxiP1OkUmFRHEE7Dxiagz6omJV8ien+p9wIgS +QcqkJlgKMwVepjuCuEyvg5oIkAPvp24yhePSJkEvvoDLvM2Kub/CM+UkN8dSgsZk ++ZBE9Oi62AWWow8/ib8Um5DNIEZsq+5CQLeBG7f5kTIBAoA9UceaEgbxzOVUCBcX +L7QsJ3pZ/ei1qx/9tChO/OXa9tleXcjGg7/q/6i6pUyZuqZlt+hk+3HtFmTXIjsM +chbUSMEJ2isv9MDamTtunt9N92A6OxUkAs68kCO/bzotldXMKZVjOohNnML5q/3U +vpsuN8NNwaNHCAM7pjols4V7ebX1lDZFR1hbj+szKMhVKzFfig1lRHafgRrR6H6P +mUK16lKzUbmvwv2IU/3wck+4UNeB/+lRmfAfBasQytnbt+5fwwNkVSrDY2Kxe0nz +2k3eIYST+ygxGuNrW9rnFbBpTJb0OE5cpgun8xxDE91AmL550AcZff+9ulDBhZg1 +eMoKUALlEdDNPffVTH8Iupn0jMnJsjXynztcEVhx4h2aA5X6/2i035uEybCn33qP +J7g30oe2C69BSC0YmkT3MjF6Wrhy+M8dU0dDggRhY6JSS8wESvwGenaPi7SZlbxb +Elmc44bHros1YfGl/xDdhju134/aMBG1GlZlReI+Rwnp9DCp04xiiJb9YKyUNaGY +7BTGWyie/WYYKbX1ZlxqWA9jxow8PM1XYHuanau1/aYT16L7E83HG3qkyuFIlLJh +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIUX3cVQ47QyJp7SOy0RPzP743W9MwwDQYJKoZIhvcNAQEL +BQAwOzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5 +MQ0wCwYDVQQKDARhc2lvMB4XDTIxMTExMTIxMTA1MloXDTI2MTExMDIxMTA1Mlow +OzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5MQ0w +CwYDVQQKDARhc2lvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyURD +LjKxTCkapmWhY0bP1NaaOPzIJTTB0dzREOlmRmBmiHpW7DaRx7qBm6jYDKQ7OCbz +30/j8K4TjHOLIwxzXhXMYTJOcN2giPHNUBvm9oEuDAhYgltArJQnBBEH+3C1hCIv +1+uhTWo0HpGXTeJnvboTZ1YgmbOgr6lMhNiu9QmPX885DxWf6sDq8mRgCDX2x8sk +Ls0HuLSo88Osjx532yEhnrZgexsByhoRD3yrKHV5mWpaunk5BMsP/XMuQHayFmbO +siqnHJoL1znGVH003PcBGmEDmoIUqhLiBi2gWGu1pmckP9loqQUTEn0aLOVclHf4 +slWq344zh4tJCpQMfQIDAQABo1AwTjAdBgNVHQ4EFgQUfiX1CMQrGDi9mIBAg9cg +m0RwLJUwHwYDVR0jBBgwFoAUfiX1CMQrGDi9mIBAg9cgm0RwLJUwDAYDVR0TBAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAnDnVNSb8z/pNFaZ6YAZ+ukfNT3jjbGm1 +10BOLqJj8s5A8/JkwjaWhky/DuGXDywgEvzXC18aNAxASeqO8h9pAZtszu6NWB4s +h3r+dEQakMacxrZ+jBL/cYLrUv9r3KMPKxaDnplkamqFA/9eNmoV7vDyGtGPZuD6 +oTROtQqqDSrxthCkqnibAfusi7RmlCdvJa0kVK7krKJZAhi8W9f32+lBPv9oq3Ns +dAxnOj/D3UnhNoIt0EdjqUdLo2U39dt5s5Syj2rFUAgfbc02Rwx65kq8AjTRlW/M +KDpGsifwIB8b7wActMUO8c3GptptNVWmFm5+Mmk54P//P3tIAx9KXw== +-----END CERTIFICATE----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIPcVUeQ7ZElgCAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECGKlFVN6/gIlBIIEyJPeknsA5dvV +WK27AZzs4wM6WrsD6ba+kPJyZTpon5pn4eoTiw4UCvo7C+21G9jCqbIbDrgTWHwH +zu6YrBFTZgRUpdLkLsyUsp4UJrZ8xJ7N/jWlG763CyluFE5oBFLz2Vt/DSDSaWdA +sKdxua/1kvw+KYoDqlObMFIspM5TrndcMnWkOgyvQAvnH0NZXFFBa4QGFrwWDrCo +m12CzMLwaPMrNFBffCTqZnL1AajT+EYqPTi+cQ5mkRpZ2cuzhdug2eki1KkD12ZN +3d8Ehl8bfbLEqRE/HnggleRRt7ia1xkzruqQp14JA2UsrioGMF5nvWgWrbyHfpui +KrCsDwDelrArW/GCki53QBQMuH8Q1YmoNrRZwlG257eA1LiJvmxRyIjKYu0RP+Q8 +EOldycy51VsPVPApUbv9r4IJldrIJiwlmRxxM36uKtFhfojnsWzJORDYI8C37uKi +UEPiD4GSEH6C0lGO94IoZPjl9z/rZ0qZx1VRHl3nxZc0AQvvj9bWMbyRwsgb6wod +P8JSy6uEib9UxuenNHzTd48GcNhJbhOqd4IV0XKhi8W1Kil3mMdc3QAwKaLTx12/ +1GrbMui061uyeM6Rf6Xao0PApDnUNmxcFSTsoarG0yH7Q0WZMgKTDCCGhhtZKlE6 +x7pRsnxiFaIpoh32EVIRI+ZXh2rXBcwa2ew0aEccRXtPFvcmdjevkrHuCggc+M+Y +seFqTHVGWf8eS6o08w095DboD0vFpZXZMRfycTbA7BiE4NYE/uc7v5cH3Ax9l2ef +zG7o9idDt+/RX7OcetxDFw4eQbq7PfjvrfXS1DcRUEyJ04emh7oxlkAUUNsFtabN +T0ggvHxcQWkYRE5oPlkbgpwKpK4LDcApXKFwCDKPur2W5Q7KHRfDLtSvZvYarJum +8j2pGpEis/bdTih29ofNsX6a0Yo5Tlj+9+1c/6/Xi7XvRk/Vbgkoa3iVQ3ckdCuZ +vO7cRYZBBs6W/Ti3hWFzPEX9FfcnSUp9bEnH4ASnmUcp8PDBJYeaI6HqpO3XbkbF +l70eDNakd2cDNjQzkFpBT7HO+HtqU3xNt9K0z2gMB7iTDVFyIzh26joCR2O8tiqS +wUJFkoLPb74GSB7WzE+gb4jXX6n9609PUoR3f896mM34uX3CsY8lA+/0ZGpHnFDA +ToKdmz6WKIAw0E20nyzLuLwPZgj7HLcR7zza4raipe9QxIdyJr5O+jzGt+OjSM9b +K1agibRE5DChqQ+P+ikOc6nG7UNyn+lKSjGEbwuzi8F0iugMgcTc/vYO8OWDNGpd +D1euA5OuVPdfatFa16Fyr4MJJIfE83C4/kSj05fdoyb6pJkOjHhUppVMe+ES5kwl +YI8RES2XVJzUSxnWsIM613YlMgIZ9xgcuIADnO7gaKJ4RQG+9wJ853Uo4+n89K7F +Y6KzihuYAUkbAw1pPo1TODom7A/gB9stqRUSQlZWmIgtnJ8wPjt/we0gzPM8LQzb +ye4KOLjH5iquFc4MU4TtN3gvp9P5R9UFrGeMImS5eMUmBQHckDNdIAtMj7M1wUpR +JVrzDXWDjC21sLn95NtNMPb+FRlt/biTV3IE3ZmX0kbuCRoH7b7hhR41Zpoajwl0 +FqYigB5gnVodGUWuBgDUqA== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/3rdparty/asio/src/examples/cpp11/timeouts/async_tcp_client.cpp b/3rdparty/asio/src/examples/cpp11/timeouts/async_tcp_client.cpp index 9ded9309f60..b8f2cbe77d2 100644 --- a/3rdparty/asio/src/examples/cpp11/timeouts/async_tcp_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/timeouts/async_tcp_client.cpp @@ -2,7 +2,7 @@ // async_tcp_client.cpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/timeouts/blocking_tcp_client.cpp b/3rdparty/asio/src/examples/cpp11/timeouts/blocking_tcp_client.cpp index 96b7b52a074..e29edc2895f 100644 --- a/3rdparty/asio/src/examples/cpp11/timeouts/blocking_tcp_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/timeouts/blocking_tcp_client.cpp @@ -2,7 +2,7 @@ // blocking_tcp_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/timeouts/blocking_token_tcp_client.cpp b/3rdparty/asio/src/examples/cpp11/timeouts/blocking_token_tcp_client.cpp index 6379642665a..085570d8b78 100644 --- a/3rdparty/asio/src/examples/cpp11/timeouts/blocking_token_tcp_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/timeouts/blocking_token_tcp_client.cpp @@ -2,7 +2,7 @@ // blocking_token_tcp_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) @@ -22,6 +22,10 @@ using asio::ip::tcp; +// NOTE: This example uses the new form of the asio::async_result trait. +// For an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + // We will use our sockets only with an io_context. using tcp_socket = asio::basic_stream_socket< tcp, asio::io_context::executor_type>; @@ -54,51 +58,26 @@ template <typename T> class async_result<close_after, void(std::error_code, T)> { public: - // An asynchronous operation's initiating function automatically creates an - // completion_handler_type object from the token. This function object is - // then called on completion of the asynchronous operation. - class completion_handler_type - { - public: - completion_handler_type(const close_after& token) - : token_(token) - { - } - - void operator()(const std::error_code& error, T t) - { - *error_ = error; - *t_ = t; - } - - private: - friend class async_result; - close_after token_; - std::error_code* error_; - T* t_; - }; - - // The async_result constructor associates the completion handler object with - // the result of the initiating function. - explicit async_result(completion_handler_type& h) - : timeout_(h.token_.timeout_), - socket_(h.token_.socket_) - { - h.error_ = &error_; - h.t_ = &t_; - } - - // The return_type typedef determines the result type of the asynchronous - // operation's initiating function. - typedef T return_type; - - // The get() function is used to obtain the result of the asynchronous - // operation's initiating function. For the close_after completion token, we - // use this function to run the io_context until the operation is complete. - return_type get() + // The initiate() function is used to launch the asynchronous operation by + // calling the operation's initiation function object. For the close_after + // completion token, we use this function to run the io_context until the + // operation is complete. + template <typename Init, typename... Args> + static T initiate(Init init, close_after token, Args&&... args) { asio::io_context& io_context = asio::query( - socket_.get_executor(), asio::execution::context); + token.socket_.get_executor(), asio::execution::context); + + // Call the operation's initiation function object to start the operation. + // A lambda is supplied as the completion handler, to be called when the + // operation completes. + std::error_code error; + T result; + init([&](std::error_code e, T t) + { + error = e; + result = t; + }, std::forward<Args>(args)...); // Restart the io_context, as it may have been left in the "stopped" state // by a previous operation. @@ -108,7 +87,7 @@ public: // the pending asynchronous operation is a composed operation, the deadline // applies to the entire operation, rather than individual operations on // the socket. - io_context.run_for(timeout_); + io_context.run_for(token.timeout_); // If the asynchronous operation completed successfully then the io_context // would have been stopped due to running out of work. If it was not @@ -117,21 +96,15 @@ public: if (!io_context.stopped()) { // Close the socket to cancel the outstanding asynchronous operation. - socket_.close(); + token.socket_.close(); // Run the io_context again until the operation completes. io_context.run(); } // If the operation failed, throw an exception. Otherwise return the result. - return error_ ? throw std::system_error(error_) : t_; + return error ? throw std::system_error(error) : result; } - -private: - std::chrono::steady_clock::duration timeout_; - tcp_socket& socket_; - std::error_code error_; - T t_; }; } // namespace asio diff --git a/3rdparty/asio/src/examples/cpp11/timeouts/blocking_udp_client.cpp b/3rdparty/asio/src/examples/cpp11/timeouts/blocking_udp_client.cpp index 01eece472f4..312f21ab656 100644 --- a/3rdparty/asio/src/examples/cpp11/timeouts/blocking_udp_client.cpp +++ b/3rdparty/asio/src/examples/cpp11/timeouts/blocking_udp_client.cpp @@ -2,7 +2,7 @@ // blocking_udp_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/timeouts/server.cpp b/3rdparty/asio/src/examples/cpp11/timeouts/server.cpp index ac1f37f140f..6e18fc60c2b 100644 --- a/3rdparty/asio/src/examples/cpp11/timeouts/server.cpp +++ b/3rdparty/asio/src/examples/cpp11/timeouts/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/timers/time_t_timer.cpp b/3rdparty/asio/src/examples/cpp11/timers/time_t_timer.cpp index 764ca586d1b..bca436d31e7 100644 --- a/3rdparty/asio/src/examples/cpp11/timers/time_t_timer.cpp +++ b/3rdparty/asio/src/examples/cpp11/timers/time_t_timer.cpp @@ -2,7 +2,7 @@ // time_t_timer.cpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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) diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/daytime1/client.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/daytime1/client.cpp new file mode 100644 index 00000000000..9d927759f5c --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/daytime1/client.cpp @@ -0,0 +1,57 @@ +// +// client.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <array> +#include <iostream> +#include <asio.hpp> + +using asio::ip::tcp; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: client <host>" << std::endl; + return 1; + } + + asio::io_context io_context; + + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = + resolver.resolve(argv[1], "daytime"); + + tcp::socket socket(io_context); + asio::connect(socket, endpoints); + + for (;;) + { + std::array<char, 128> buf; + std::error_code error; + + size_t len = socket.read_some(asio::buffer(buf), error); + + if (error == asio::error::eof) + break; // Connection closed cleanly by peer. + else if (error) + throw std::system_error(error); // Some other error. + + std::cout.write(buf.data(), len); + } + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/daytime2/server.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/daytime2/server.cpp new file mode 100644 index 00000000000..971149d6e8d --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/daytime2/server.cpp @@ -0,0 +1,50 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <ctime> +#include <iostream> +#include <string> +#include <asio.hpp> + +using asio::ip::tcp; + +std::string make_daytime_string() +{ + using namespace std; // For time_t, time and ctime; + time_t now = time(0); + return ctime(&now); +} + +int main() +{ + try + { + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 13)); + + for (;;) + { + tcp::socket socket(io_context); + acceptor.accept(socket); + + std::string message = make_daytime_string(); + + std::error_code ignored_error; + asio::write(socket, asio::buffer(message), ignored_error); + } + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/daytime3/server.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/daytime3/server.cpp new file mode 100644 index 00000000000..339de72d4a7 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/daytime3/server.cpp @@ -0,0 +1,118 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <ctime> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include <asio.hpp> + +using asio::ip::tcp; + +std::string make_daytime_string() +{ + using namespace std; // For time_t, time and ctime; + time_t now = time(0); + return ctime(&now); +} + +class tcp_connection + : public std::enable_shared_from_this<tcp_connection> +{ +public: + typedef std::shared_ptr<tcp_connection> pointer; + + static pointer create(asio::io_context& io_context) + { + return pointer(new tcp_connection(io_context)); + } + + tcp::socket& socket() + { + return socket_; + } + + void start() + { + message_ = make_daytime_string(); + + asio::async_write(socket_, asio::buffer(message_), + std::bind(&tcp_connection::handle_write, shared_from_this(), + asio::placeholders::error, + asio::placeholders::bytes_transferred)); + } + +private: + tcp_connection(asio::io_context& io_context) + : socket_(io_context) + { + } + + void handle_write(const std::error_code& /*error*/, + size_t /*bytes_transferred*/) + { + } + + tcp::socket socket_; + std::string message_; +}; + +class tcp_server +{ +public: + tcp_server(asio::io_context& io_context) + : io_context_(io_context), + acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) + { + start_accept(); + } + +private: + void start_accept() + { + tcp_connection::pointer new_connection = + tcp_connection::create(io_context_); + + acceptor_.async_accept(new_connection->socket(), + std::bind(&tcp_server::handle_accept, this, new_connection, + asio::placeholders::error)); + } + + void handle_accept(tcp_connection::pointer new_connection, + const std::error_code& error) + { + if (!error) + { + new_connection->start(); + } + + start_accept(); + } + + asio::io_context& io_context_; + tcp::acceptor acceptor_; +}; + +int main() +{ + try + { + asio::io_context io_context; + tcp_server server(io_context); + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/daytime4/client.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/daytime4/client.cpp new file mode 100644 index 00000000000..15f3d5d4e98 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/daytime4/client.cpp @@ -0,0 +1,52 @@ +// +// client.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <array> +#include <iostream> +#include <asio.hpp> + +using asio::ip::udp; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: client <host>" << std::endl; + return 1; + } + + asio::io_context io_context; + + udp::resolver resolver(io_context); + udp::endpoint receiver_endpoint = + *resolver.resolve(udp::v4(), argv[1], "daytime").begin(); + + udp::socket socket(io_context); + socket.open(udp::v4()); + + std::array<char, 1> send_buf = {{ 0 }}; + socket.send_to(asio::buffer(send_buf), receiver_endpoint); + + std::array<char, 128> recv_buf; + udp::endpoint sender_endpoint; + size_t len = socket.receive_from( + asio::buffer(recv_buf), sender_endpoint); + + std::cout.write(recv_buf.data(), len); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/daytime5/server.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/daytime5/server.cpp new file mode 100644 index 00000000000..f47c9fa713b --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/daytime5/server.cpp @@ -0,0 +1,53 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <array> +#include <ctime> +#include <iostream> +#include <string> +#include <asio.hpp> + +using asio::ip::udp; + +std::string make_daytime_string() +{ + using namespace std; // For time_t, time and ctime; + time_t now = time(0); + return ctime(&now); +} + +int main() +{ + try + { + asio::io_context io_context; + + udp::socket socket(io_context, udp::endpoint(udp::v4(), 13)); + + for (;;) + { + std::array<char, 1> recv_buf; + udp::endpoint remote_endpoint; + socket.receive_from(asio::buffer(recv_buf), remote_endpoint); + + std::string message = make_daytime_string(); + + std::error_code ignored_error; + socket.send_to(asio::buffer(message), + remote_endpoint, 0, ignored_error); + } + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/daytime6/server.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/daytime6/server.cpp new file mode 100644 index 00000000000..42c80795a9e --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/daytime6/server.cpp @@ -0,0 +1,89 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <array> +#include <ctime> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include <asio.hpp> + +using asio::ip::udp; + +std::string make_daytime_string() +{ + using namespace std; // For time_t, time and ctime; + time_t now = time(0); + return ctime(&now); +} + +class udp_server +{ +public: + udp_server(asio::io_context& io_context) + : socket_(io_context, udp::endpoint(udp::v4(), 13)) + { + start_receive(); + } + +private: + void start_receive() + { + socket_.async_receive_from( + asio::buffer(recv_buffer_), remote_endpoint_, + std::bind(&udp_server::handle_receive, this, + asio::placeholders::error, + asio::placeholders::bytes_transferred)); + } + + void handle_receive(const std::error_code& error, + std::size_t /*bytes_transferred*/) + { + if (!error) + { + std::shared_ptr<std::string> message( + new std::string(make_daytime_string())); + + socket_.async_send_to(asio::buffer(*message), remote_endpoint_, + std::bind(&udp_server::handle_send, this, message, + asio::placeholders::error, + asio::placeholders::bytes_transferred)); + + start_receive(); + } + } + + void handle_send(std::shared_ptr<std::string> /*message*/, + const std::error_code& /*error*/, + std::size_t /*bytes_transferred*/) + { + } + + udp::socket socket_; + udp::endpoint remote_endpoint_; + std::array<char, 1> recv_buffer_; +}; + +int main() +{ + try + { + asio::io_context io_context; + udp_server server(io_context); + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/daytime7/server.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/daytime7/server.cpp new file mode 100644 index 00000000000..9c9c22edeb2 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/daytime7/server.cpp @@ -0,0 +1,159 @@ +// +// server.cpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <array> +#include <ctime> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include <asio.hpp> + +using asio::ip::tcp; +using asio::ip::udp; + +std::string make_daytime_string() +{ + using namespace std; // For time_t, time and ctime; + time_t now = time(0); + return ctime(&now); +} + +class tcp_connection + : public std::enable_shared_from_this<tcp_connection> +{ +public: + typedef std::shared_ptr<tcp_connection> pointer; + + static pointer create(asio::io_context& io_context) + { + return pointer(new tcp_connection(io_context)); + } + + tcp::socket& socket() + { + return socket_; + } + + void start() + { + message_ = make_daytime_string(); + + asio::async_write(socket_, asio::buffer(message_), + std::bind(&tcp_connection::handle_write, shared_from_this())); + } + +private: + tcp_connection(asio::io_context& io_context) + : socket_(io_context) + { + } + + void handle_write() + { + } + + tcp::socket socket_; + std::string message_; +}; + +class tcp_server +{ +public: + tcp_server(asio::io_context& io_context) + : io_context_(io_context), + acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) + { + start_accept(); + } + +private: + void start_accept() + { + tcp_connection::pointer new_connection = + tcp_connection::create(io_context_); + + acceptor_.async_accept(new_connection->socket(), + std::bind(&tcp_server::handle_accept, this, new_connection, + asio::placeholders::error)); + } + + void handle_accept(tcp_connection::pointer new_connection, + const std::error_code& error) + { + if (!error) + { + new_connection->start(); + } + + start_accept(); + } + + asio::io_context& io_context_; + tcp::acceptor acceptor_; +}; + +class udp_server +{ +public: + udp_server(asio::io_context& io_context) + : socket_(io_context, udp::endpoint(udp::v4(), 13)) + { + start_receive(); + } + +private: + void start_receive() + { + socket_.async_receive_from( + asio::buffer(recv_buffer_), remote_endpoint_, + std::bind(&udp_server::handle_receive, this, + asio::placeholders::error)); + } + + void handle_receive(const std::error_code& error) + { + if (!error) + { + std::shared_ptr<std::string> message( + new std::string(make_daytime_string())); + + socket_.async_send_to(asio::buffer(*message), remote_endpoint_, + std::bind(&udp_server::handle_send, this, message)); + + start_receive(); + } + } + + void handle_send(std::shared_ptr<std::string> /*message*/) + { + } + + udp::socket socket_; + udp::endpoint remote_endpoint_; + std::array<char, 1> recv_buffer_; +}; + +int main() +{ + try + { + asio::io_context io_context; + tcp_server server1(io_context); + udp_server server2(io_context); + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/timer1/timer.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/timer1/timer.cpp new file mode 100644 index 00000000000..37577dcb65f --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/timer1/timer.cpp @@ -0,0 +1,24 @@ +// +// timer.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include <asio.hpp> + +int main() +{ + asio::io_context io; + + asio::steady_timer t(io, asio::chrono::seconds(5)); + t.wait(); + + std::cout << "Hello, world!" << std::endl; + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/timer2/timer.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/timer2/timer.cpp new file mode 100644 index 00000000000..c1620d78fa5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/timer2/timer.cpp @@ -0,0 +1,29 @@ +// +// timer.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <iostream> +#include <asio.hpp> + +void print(const std::error_code& /*e*/) +{ + std::cout << "Hello, world!" << std::endl; +} + +int main() +{ + asio::io_context io; + + asio::steady_timer t(io, asio::chrono::seconds(5)); + t.async_wait(&print); + + io.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/timer3/timer.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/timer3/timer.cpp new file mode 100644 index 00000000000..990ea069739 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/timer3/timer.cpp @@ -0,0 +1,43 @@ +// +// timer.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <functional> +#include <iostream> +#include <asio.hpp> + +void print(const std::error_code& /*e*/, + asio::steady_timer* t, int* count) +{ + if (*count < 5) + { + std::cout << *count << std::endl; + ++(*count); + + t->expires_at(t->expiry() + asio::chrono::seconds(1)); + t->async_wait(std::bind(print, + asio::placeholders::error, t, count)); + } +} + +int main() +{ + asio::io_context io; + + int count = 0; + asio::steady_timer t(io, asio::chrono::seconds(1)); + t.async_wait(std::bind(print, + asio::placeholders::error, &t, &count)); + + io.run(); + + std::cout << "Final count is " << count << std::endl; + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/timer4/timer.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/timer4/timer.cpp new file mode 100644 index 00000000000..7bfdd3e43a8 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/timer4/timer.cpp @@ -0,0 +1,54 @@ +// +// timer.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <functional> +#include <iostream> +#include <asio.hpp> + +class printer +{ +public: + printer(asio::io_context& io) + : timer_(io, asio::chrono::seconds(1)), + count_(0) + { + timer_.async_wait(std::bind(&printer::print, this)); + } + + ~printer() + { + std::cout << "Final count is " << count_ << std::endl; + } + + void print() + { + if (count_ < 5) + { + std::cout << count_ << std::endl; + ++count_; + + timer_.expires_at(timer_.expiry() + asio::chrono::seconds(1)); + timer_.async_wait(std::bind(&printer::print, this)); + } + } + +private: + asio::steady_timer timer_; + int count_; +}; + +int main() +{ + asio::io_context io; + printer p(io); + io.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/tutorial/timer5/timer.cpp b/3rdparty/asio/src/examples/cpp11/tutorial/timer5/timer.cpp new file mode 100644 index 00000000000..61830691e7a --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/tutorial/timer5/timer.cpp @@ -0,0 +1,81 @@ +// +// timer.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <functional> +#include <iostream> +#include <thread> +#include <asio.hpp> + +class printer +{ +public: + printer(asio::io_context& io) + : strand_(asio::make_strand(io)), + timer1_(io, asio::chrono::seconds(1)), + timer2_(io, asio::chrono::seconds(1)), + count_(0) + { + timer1_.async_wait(asio::bind_executor(strand_, + std::bind(&printer::print1, this))); + + timer2_.async_wait(asio::bind_executor(strand_, + std::bind(&printer::print2, this))); + } + + ~printer() + { + std::cout << "Final count is " << count_ << std::endl; + } + + void print1() + { + if (count_ < 10) + { + std::cout << "Timer 1: " << count_ << std::endl; + ++count_; + + timer1_.expires_at(timer1_.expiry() + asio::chrono::seconds(1)); + + timer1_.async_wait(asio::bind_executor(strand_, + std::bind(&printer::print1, this))); + } + } + + void print2() + { + if (count_ < 10) + { + std::cout << "Timer 2: " << count_ << std::endl; + ++count_; + + timer2_.expires_at(timer2_.expiry() + asio::chrono::seconds(1)); + + timer2_.async_wait(asio::bind_executor(strand_, + std::bind(&printer::print2, this))); + } + } + +private: + asio::strand<asio::io_context::executor_type> strand_; + asio::steady_timer timer1_; + asio::steady_timer timer2_; + int count_; +}; + +int main() +{ + asio::io_context io; + printer p(io); + std::thread t([&]{ io.run(); }); + io.run(); + t.join(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp11/type_erasure/line_reader.hpp b/3rdparty/asio/src/examples/cpp11/type_erasure/line_reader.hpp new file mode 100644 index 00000000000..87f05486b79 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/type_erasure/line_reader.hpp @@ -0,0 +1,48 @@ +// +// line_reader.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 LINE_READER_HPP +#define LINE_READER_HPP + +#include <asio/any_completion_handler.hpp> +#include <asio/async_result.hpp> +#include <asio/error.hpp> +#include <string> + +class line_reader +{ +private: + virtual void async_read_line_impl(std::string prompt, + asio::any_completion_handler<void(std::error_code, std::string)> handler) = 0; + + struct initiate_read_line + { + template <typename Handler> + void operator()(Handler handler, line_reader* self, std::string prompt) + { + self->async_read_line_impl(std::move(prompt), std::move(handler)); + } + }; + +public: + virtual ~line_reader() {} + + template <typename CompletionToken> + auto async_read_line(std::string prompt, CompletionToken&& token) + -> decltype( + asio::async_initiate<CompletionToken, void(std::error_code, std::string)>( + initiate_read_line(), token, this, prompt)) + { + return asio::async_initiate<CompletionToken, void(std::error_code, std::string)>( + initiate_read_line(), token, this, prompt); + } +}; + +#endif // LINE_READER_HPP diff --git a/3rdparty/asio/src/examples/cpp11/type_erasure/main.cpp b/3rdparty/asio/src/examples/cpp11/type_erasure/main.cpp new file mode 100644 index 00000000000..2111de6853b --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/type_erasure/main.cpp @@ -0,0 +1,60 @@ +// +// main.cpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "line_reader.hpp" +#include "sleep.hpp" +#include "stdin_line_reader.hpp" +#include <asio/coroutine.hpp> +#include <asio/detached.hpp> +#include <asio/io_context.hpp> +#include <asio/use_awaitable.hpp> +#include <iostream> + +#include <asio/yield.hpp> + +class read_loop : asio::coroutine +{ +public: + read_loop(asio::any_io_executor e, line_reader& r) + : executor(std::move(e)), + reader(r) + { + } + + void operator()(std::error_code ec = {}, std::string line = {}) + { + reenter (this) + { + for (i = 0; i < 10; ++i) + { + yield reader.async_read_line("Enter something: ", *this); + if (ec) break; + std::cout << line; + yield async_sleep(executor, std::chrono::seconds(1), *this); + if (ec) break; + } + } + } + +private: + asio::any_io_executor executor; + line_reader& reader; + int i; +}; + +#include <asio/unyield.hpp> + +int main() +{ + asio::io_context ctx{1}; + stdin_line_reader reader{ctx.get_executor()}; + read_loop(ctx.get_executor(), reader)(); + ctx.run(); +} diff --git a/3rdparty/asio/src/examples/cpp11/type_erasure/sleep.cpp b/3rdparty/asio/src/examples/cpp11/type_erasure/sleep.cpp new file mode 100644 index 00000000000..b605866ebd7 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/type_erasure/sleep.cpp @@ -0,0 +1,22 @@ +// +// sleep.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "sleep.hpp" +#include <asio/consign.hpp> +#include <asio/steady_timer.hpp> +#include <memory> + +void async_sleep_impl( + asio::any_completion_handler<void(std::error_code)> handler, + asio::any_io_executor ex, std::chrono::nanoseconds duration) +{ + auto timer = std::make_shared<asio::steady_timer>(ex, duration); + timer->async_wait(asio::consign(std::move(handler), timer)); +} diff --git a/3rdparty/asio/src/examples/cpp11/type_erasure/sleep.hpp b/3rdparty/asio/src/examples/cpp11/type_erasure/sleep.hpp new file mode 100644 index 00000000000..299397a833c --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/type_erasure/sleep.hpp @@ -0,0 +1,35 @@ +// +// sleep.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 SLEEP_HPP +#define SLEEP_HPP + +#include <asio/any_completion_handler.hpp> +#include <asio/any_io_executor.hpp> +#include <asio/async_result.hpp> +#include <asio/error.hpp> +#include <chrono> + +void async_sleep_impl( + asio::any_completion_handler<void(std::error_code)> handler, + asio::any_io_executor ex, std::chrono::nanoseconds duration); + +template <typename CompletionToken> +inline auto async_sleep(asio::any_io_executor ex, + std::chrono::nanoseconds duration, CompletionToken&& token) + -> decltype( + asio::async_initiate<CompletionToken, void(std::error_code)>( + async_sleep_impl, token, std::move(ex), duration)) +{ + return asio::async_initiate<CompletionToken, void(std::error_code)>( + async_sleep_impl, token, std::move(ex), duration); +} + +#endif // SLEEP_HPP diff --git a/3rdparty/asio/src/examples/cpp11/type_erasure/stdin_line_reader.cpp b/3rdparty/asio/src/examples/cpp11/type_erasure/stdin_line_reader.cpp new file mode 100644 index 00000000000..d2e25e437a6 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/type_erasure/stdin_line_reader.cpp @@ -0,0 +1,44 @@ +// +// stdin_line_reader.cpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include "stdin_line_reader.hpp" +#include <asio/deferred.hpp> +#include <asio/read_until.hpp> +#include <iostream> + +stdin_line_reader::stdin_line_reader(asio::any_io_executor ex) + : stdin_(ex, ::dup(STDIN_FILENO)) +{ +} + +void stdin_line_reader::async_read_line_impl(std::string prompt, + asio::any_completion_handler<void(std::error_code, std::string)> handler) +{ + std::cout << prompt; + std::cout.flush(); + + asio::async_read_until(stdin_, asio::dynamic_buffer(buffer_), '\n', + asio::deferred( + [this](std::error_code ec, std::size_t n) + { + if (!ec) + { + std::string result = buffer_.substr(0, n); + buffer_.erase(0, n); + return asio::deferred.values(ec, std::move(result)); + } + else + { + return asio::deferred.values(ec, std::string{}); + } + } + ) + )(std::move(handler)); +} diff --git a/3rdparty/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp b/3rdparty/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp new file mode 100644 index 00000000000..43e67424367 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp @@ -0,0 +1,30 @@ +// +// stdin_line_reader.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 STDIN_LINE_READER_HPP +#define STDIN_LINE_READER_HPP + +#include "line_reader.hpp" +#include <asio/posix/stream_descriptor.hpp> + +class stdin_line_reader : public line_reader +{ +public: + explicit stdin_line_reader(asio::any_io_executor ex); + +private: + void async_read_line_impl(std::string prompt, + asio::any_completion_handler<void(std::error_code, std::string)> handler) override; + + asio::posix::stream_descriptor stdin_; + std::string buffer_; +}; + +#endif diff --git a/3rdparty/asio/src/examples/cpp11/windows/transmit_file.cpp b/3rdparty/asio/src/examples/cpp11/windows/transmit_file.cpp new file mode 100644 index 00000000000..0ffd0486c43 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp11/windows/transmit_file.cpp @@ -0,0 +1,176 @@ +// +// transmit_file.cpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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) +// + +#include <ctime> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include "asio.hpp" + +#if defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) + +using asio::ip::tcp; +using asio::windows::overlapped_ptr; +using asio::windows::random_access_handle; + +typedef asio::basic_stream_socket<tcp, + asio::io_context::executor_type> tcp_socket; + +typedef asio::basic_socket_acceptor<tcp, + asio::io_context::executor_type> tcp_acceptor; + +// A wrapper for the TransmitFile overlapped I/O operation. +template <typename Handler> +void transmit_file(tcp_socket& socket, + random_access_handle& file, Handler handler) +{ + // Construct an OVERLAPPED-derived object to contain the handler. + overlapped_ptr overlapped(socket.get_executor().context(), handler); + + // Initiate the TransmitFile operation. + BOOL ok = ::TransmitFile(socket.native_handle(), + file.native_handle(), 0, 0, overlapped.get(), 0, 0); + DWORD last_error = ::GetLastError(); + + // Check if the operation completed immediately. + if (!ok && last_error != ERROR_IO_PENDING) + { + // The operation completed immediately, so a completion notification needs + // to be posted. When complete() is called, ownership of the OVERLAPPED- + // derived object passes to the io_context. + std::error_code ec(last_error, + asio::error::get_system_category()); + overlapped.complete(ec, 0); + } + else + { + // The operation was successfully initiated, so ownership of the + // OVERLAPPED-derived object has passed to the io_context. + overlapped.release(); + } +} + +class connection + : public std::enable_shared_from_this<connection> +{ +public: + typedef std::shared_ptr<connection> pointer; + + static pointer create(asio::io_context& io_context, + const std::string& filename) + { + return pointer(new connection(io_context, filename)); + } + + tcp_socket& socket() + { + return socket_; + } + + void start() + { + std::error_code ec; + file_.assign(::CreateFile(filename_.c_str(), GENERIC_READ, 0, 0, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0), ec); + if (file_.is_open()) + { + transmit_file(socket_, file_, + std::bind(&connection::handle_write, shared_from_this(), + asio::placeholders::error, + asio::placeholders::bytes_transferred)); + } + } + +private: + connection(asio::io_context& io_context, const std::string& filename) + : socket_(io_context), + filename_(filename), + file_(io_context) + { + } + + void handle_write(const std::error_code& /*error*/, + size_t /*bytes_transferred*/) + { + std::error_code ignored_ec; + socket_.shutdown(tcp_socket::shutdown_both, ignored_ec); + } + + tcp_socket socket_; + std::string filename_; + random_access_handle file_; +}; + +class server +{ +public: + server(asio::io_context& io_context, + unsigned short port, const std::string& filename) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), + filename_(filename) + { + start_accept(); + } + +private: + void start_accept() + { + connection::pointer new_connection = + connection::create(acceptor_.get_executor().context(), filename_); + + acceptor_.async_accept(new_connection->socket(), + std::bind(&server::handle_accept, this, new_connection, + asio::placeholders::error)); + } + + void handle_accept(connection::pointer new_connection, + const std::error_code& error) + { + if (!error) + { + new_connection->start(); + } + + start_accept(); + } + + tcp_acceptor acceptor_; + std::string filename_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cerr << "Usage: transmit_file <port> <filename>\n"; + return 1; + } + + asio::io_context io_context; + + using namespace std; // For atoi. + server s(io_context, atoi(argv[1]), argv[2]); + + io_context.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} + +#else // defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) +# error Overlapped I/O not available on this platform +#endif // defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) |